Skip to main content
Supported on: iOS SDK 1.0.61+ · Android SDK 1.0.33+ · React Native SDK 1.0.4+
The AppDNA React Native SDK renders rich media — Lottie animations, Rive animations, video, and images — through native platform pipelines on each side: SwiftUI + CoreAnimation on iOS, Jetpack Compose + Rive’s Android renderer on Android. Animations and effects look and feel identical to anything you would build by hand. All rich media content is configured in the AppDNA Console, no TypeScript code changes required.

Supported Formats

Lottie Animations

Lottie animations are rendered natively on both platforms. On iOS the SDK uses lottie-ios (added as a separate SPM dependency in your iOS host project), and on Android Lottie Compose is bundled directly into the AppDNA SDK.
  • Remote URL — provide a URL to a .json Lottie file
  • Inline JSON — embed the animation JSON directly in the config
  • Controls — autoplay, loop, speed, play-on-scroll, play-on-tap
  • Color overrides — remap colors in the animation without re-exporting
Lottie is supported in onboarding content blocks, paywall sections, in-app message hero areas, and survey thank-you screens.

Rive Animations

Rive animations are rendered using the native Rive runtime on each platform. iOS requires adding rive-ios as a separate SPM dependency in your iOS host project. The Android Rive runtime is bundled with the AppDNA Android SDK.
  • Remote URL — provide a URL to a .riv file
  • Artboard selection — choose which artboard to display
  • State machine — drive interactive animations with state machine inputs
  • Trigger on completion — fire a state machine trigger when the step or flow completes
Rive is supported in onboarding content blocks and paywall sections.

Video

Inline video playback uses native players on each platform — AVPlayer on iOS, ExoPlayer on Android. React Native sees a fully rendered native view, so playback performance is identical to a hand-written native implementation.
  • Remote URL — provide a URL to an MP4 or HLS video
  • Thumbnail — optional poster image shown before playback
  • Controls — autoplay, loop, muted, show/hide controls
  • Sizing — configurable height and corner radius
Video is supported in onboarding content blocks, paywall sections, and in-app message hero areas.

Images

Remote images are fetched and cached by the native SDKs:
  • Remote URL — standard JPEG, PNG, and WebP supported on both platforms
  • GIF — animated GIFs are supported in in-app message hero areas and push notification rich content
  • SVG — supported on both platforms with native rasterization
  • Corner radius, sizing, content mode — configured in the Console

Asset URL Conventions

Each rich-media block in the AppDNA Console uses a typed URL field:
FieldBlock typeDescription
lottie_urllottieRemote URL to a .json Lottie animation
rive_urlriveRemote URL to a .riv Rive animation
video_urlvideoRemote URL to an MP4 or HLS video stream
image_urlimageRemote URL to a JPEG, PNG, WebP, or SVG file
thumbnail_urlvideoOptional poster image for the video block
Any of these fields can also accept inline data where supported (e.g. Lottie supports inline JSON). The SDK auto-detects the format from the URL extension or the inline payload.

Embedding Rich Media in Paywalls

Rich media inside paywalls is configured per section. The console exposes section types like paywall_header, paywall_features, and paywall_cta, each of which can host an image, Lottie animation, Rive animation, or video. The React Native SDK simply presents the paywall and the native renderer handles the rest:
import { AppDNA } from '@appdna/react-native-sdk';

try {
  await AppDNA.paywall.present('premium_upgrade', { placement: 'settings' });
} catch (e) {
  console.log('Paywall not available:', e);
}
Common patterns:
  • Hero Lottie — attach a Lottie URL to the paywall_header section to play a looping product animation while the user reads features.
  • Feature illustrations — inside paywall_features, each feature row can carry an inline icon (Lucide / SF Symbols / Material / emoji) or a remote image.
  • Video proof — a short looping product demo can be embedded into a section with paywall_video style.
  • CTA pulse — the paywall_cta section supports CTA animations (pulse, glow, bounce) configured entirely from the Console.

Embedding Rich Media in Onboarding

Onboarding steps are composed of an ordered list of content blocks. Each block has a type and optional styling. Supported block types include:
Block TypeDescription
headingStyled heading (level 1-6)
textBody text with styling
imageRemote image with corner radius and sizing
buttonAction button (next, skip, link, permission)
spacerVertical spacing
listBullet, numbered, or checklist
dividerHorizontal separator
badgeColored badge label
iconIcon with emoji or icon reference
toggleSwitch with label and description
videoInline video player
lottieLottie animation
riveRive animation
Blocks are added in the Console — the React Native SDK simply presents the flow:
try {
  await AppDNA.onboarding.present('main_flow');
} catch (e) {
  console.log('Flow config not available:', e);
}

Embedding Rich Media in In-App Messages

In-app messages support a hero area at the top of the modal, banner, or fullscreen layout. The hero can host:
  • An image (with optional GIF playback)
  • A Lottie animation
  • A short looping video
The rest of the message body uses the same content block system as onboarding, so you can mix icons, badges, headings, text, and CTAs underneath the hero. In-app messages are triggered by event rules in the Console, but you can also gate display with an AppDNAInAppMessageDelegate:
import { AppDNA, AppDNAInAppMessageDelegate } from '@appdna/react-native-sdk';

const messageObserver: AppDNAInAppMessageDelegate = {
  onMessageShown(messageId, trigger) {
    console.log(`Message shown: ${messageId}`);
  },

  onMessageAction(messageId, action, data) {
    console.log(`Message action: ${action}`);
  },

  onMessageDismissed(messageId) {
    console.log(`Message dismissed: ${messageId}`);
  },

  shouldShowMessage(messageId) {
    // Return false to suppress display.
    return true;
  },
};

AppDNA.inAppMessages.setDelegate(messageObserver);

Animation Playback Control

All animation playback is configured per section / per content block in the AppDNA Console. The native renderers honor the data fields embedded in the config:
FieldApplies toDescription
autoplayLottie, Rive, videoStart playing as soon as the view is on screen
loopLottie, Rive, videoLoop playback indefinitely
speedLottiePlayback speed multiplier (e.g. 1.5)
mutedVideoMute audio
show_controlsVideoShow the native player chrome
play_on_tapLottiePlay once when the user taps the surface
play_on_scrollLottieTie progress to scroll position
artboardRiveChoose which artboard to display
state_machineRiveName of the state machine to drive
These fields are wired automatically by the renderer — you do not need to forward them through any TypeScript bridge.

Local Asset Embedding

For shipping assets inside the app bundle (instead of downloading them at runtime), use platform-native asset locations:
  • iOS — drop the .json / .riv / video file into your iOS host project’s asset catalog or main bundle.
  • Android — drop the asset into app/src/main/assets/ (or res/raw/ for video).
  • Console — reference the bundled asset with an asset:// URL (e.g. asset://intro.json).
The native renderer resolves asset:// URLs against the host app bundle before falling back to network. Assets bundled via the Metro packager (require('./assets/...')) are not visible to the native renderers, so put bundled rich media in the iOS / Android native locations described above.

Fallback Behavior

The native renderers degrade gracefully when an asset cannot be loaded:
  • Lottie / Rive — if the file is missing, malformed, or the network request fails, the block is skipped (no empty space, no crash). The next block in the layout takes its slot.
  • Video — if the video URL is unreachable, the optional thumbnail_url is shown instead. If no thumbnail is configured, the block is skipped.
  • Image — if the image URL is unreachable, the block is skipped. There is no broken-image placeholder.
  • Inline JSON Lottie — if the inline JSON is malformed, the block is skipped and a debug log is emitted.
All fallbacks are silent in release builds. In debug builds, the native SDKs emit warnings you can see in Xcode / Logcat.

Performance Notes

  • Lazy loading — rich-media blocks are loaded on demand. A Lottie / Rive / video asset is only fetched when its block enters the visible viewport.
  • Asset caching — remote assets are cached by the native HTTP stack (URLCache on iOS, OkHttp disk cache on Android). Subsequent presentations reuse the cached file.
  • Memory — the native renderers tear down decoded animations when the host view is dismissed, so animations do not accumulate memory across flows.
  • Cold start — avoid placing large video files on the very first onboarding step. Use a Lottie or static image for the welcome step and put video on later steps so playback starts after configuration is fully loaded.
  • Inline JSON — inline Lottie payloads add to the config bundle size. Prefer remote URLs for animations larger than ~50 KB to keep config refreshes fast.

Icons

The SDK supports structured icon references across all modules. Icons resolve to platform-native equivalents:
LibraryDescriptionExample
lucideMapped to SF Symbols (iOS) / Material Icons (Android)"heart"
sf-symbolsNative SF Symbols on iOS; mapped to Material on Android"star.fill"
materialNative Material Icons on Android; mapped to SF Symbols on iOS"favorite"
emojiUnicode emoji characters"fire"
Icons are used in onboarding content blocks, paywall feature lists, in-app message CTA buttons, and survey question options.

Visual Effects

Visual effects (haptics, particle effects, blur backdrops) are rendered by the native SDKs and configured in the Console. The React Native SDK does not need any wiring — effects fire automatically based on the triggers attached to the section or step.

Haptic Feedback

Haptic feedback is triggered automatically based on Console configuration. Supported haptic types:
TypeDescription
lightSubtle tap
mediumMedium tap
heavyStrong tap
selectionSelection change feedback
successSuccess notification
warningWarning notification
errorError notification
Haptic triggers can be configured for:
  • Step advances (onboarding)
  • Button taps
  • Plan selection (paywalls)
  • Option selection (surveys, forms)
  • Toggle changes
  • Form submission
  • Error and success states

Particle Effects

Particle effects overlay the current screen. Supported effect types:
TypeDescription
confettiColorful falling confetti
sparkleSparkling particles
fireworksBurst effect
snowFalling snowflakes
heartsFloating hearts
Each effect has a trigger (on_appear, on_step_complete, on_purchase, on_flow_complete), duration, intensity (light, medium, heavy), and optional custom colors.

Blur / Glassmorphism

Blur backdrops use the native platform’s high-performance blur primitive (iOS UIVisualEffectView, Android RenderEffect) for performant glassmorphism effects:
  • Radius — blur intensity
  • Tint — overlay color tint
  • Saturation — color saturation adjustment
Blur is supported as a backdrop for in-app message modals and fullscreen overlays.

Styling

All visual elements support fine-grained styling through the Console:
  • Text styles — font family, size, weight, color, alignment, line height, letter spacing, opacity
  • Backgrounds — solid color, linear/radial gradient, or remote image with overlay
  • Borders — width, color, style, and per-corner radius
  • Shadows — offset, blur, spread, and color
  • Spacing — per-side padding and margin
  • Animations — entry animations (slide, fade, scale), section stagger, CTA pulse/glow/bounce, dismiss animations
The native SDKs use platform-native fonts only. Custom web fonts are not supported. Specify system font families in the Console and the SDK will render them using each platform’s default typeface.

Dynamic Content Templates

Rich media content supports template interpolation using {{variable}} syntax. Available namespaces:
NamespaceExampleSource
user.*{{user.userId}}Identified user traits
session.*{{session.selected_plan}}App-defined session data
onboarding.*{{onboarding.step1.name}}Onboarding form responses
computed.*{{computed.custom_value}}Data from async hooks
device.*{{device.platform}}Device info (platform, OS, locale, country)
remote_config.*{{remote_config.app_name}}Remote config values
Use the pipe syntax for fallback values: {{user.name | there}} renders as "there" if the user name is not set.

No TypeScript Code Required

All rich media features are configured in the AppDNA Console. The React Native SDK forwards a configuration ID to the native renderer, which handles all decoding, layout, and animation. You do not need to write any TypeScript code to use Lottie, Rive, video, haptics, particles, blur, icons, or content blocks.