Development of Repost and Sharing System in a Mobile App
The client asks for a "Share" button, and we spend a week debugging push and deep link. A familiar situation: on Android, the image doesn't send due to FileProvider; on iOS, Universal Links don't work — the link opens Safari. For example, a social network project for photographers required reposting others' work to the feed and sending links to messengers. On iOS, Universal Links weren't configured due to an error in apple-app-site-association — the solution involved checking the MIME type and correct JSON structure. On Android — configuring intent-filter for App Links and fallback to Chrome. Result — a complete repost and sharing system in 2-3 days from scratch. We'll cover both tasks, show working solutions, and compare approaches.
Internal Repost: Which Data Model to Choose?
Two approaches:
- Content copying — new post with
reposted_from_idfield. Simple to display, but when the original is edited, the copy becomes stale. - Reference to original — post with
repost_of_id, no body copied, fetched on request. When the original is deleted, the repost shows "Original deleted". This approach is used by Telegram and Twitter/X. It reduces data duplication by 3x and automatically syncs with the original.
In the feed, the repost is rendered as an embedded card of the original inside the reposter's cell.
// iOS — post cell with embedded card if let repostOf = post.repostOf { // Draw RepostCardView inside PostCell let repostCard = RepostCardView(post: repostOf) contentStack.addArrangedSubview(repostCard) } The card is a UIView with rounded corners, CALayer.borderColor stroke, avatar and author name of the original. Repost of a repost displays only one nesting level.
On Compose: if (post.repostOf != null) EmbeddedPostCard(post = post.repostOf).
How to Avoid Duplicate Reposts?
Table reposts (user_id, original_post_id, UNIQUE) — a user can repost an original only once. After pressing, the button highlights, pressing again cancels the repost (un-repost). Counter reposts_count in the original's table.
Comparison of Repost Approaches
| Characteristic | Content Copying | Reference to Original |
|---|---|---|
| Data duplication | Yes | No |
| Auto-sync | No | Yes |
| Behavior when original deleted | Post remains | Shows "Original deleted" |
| Used by | Rarely | Telegram, Twitter/X |
Why External Sharing Is Harder Than It Seems?
iOS
let items: [Any] = [postText, URL(string: deeplink)!] let vc = UIActivityViewController(activityItems: items, applicationActivities: nil) // On iPad, need popoverPresentationController vc.popoverPresentationController?.sourceView = shareButton present(vc, animated: true) For image — render UIView to UIImage via UIGraphicsImageRenderer. Android
val intent = Intent(Intent.ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, "$postText\n$deeplinkUrl") } startActivity(Intent.createChooser(intent, "Share")) For images — Intent.ACTION_SEND with type = "image/*" and URI via FileProvider. Direct file:// URI doesn't work on Android 7+, only content://.
Flutter
await Share.shareXFiles([XFile(imagePath)], text: '$postText\n$deeplinkUrl'); How to Set Up Deep Links for Sharing?
External sharing without a deep link loses its purpose. The link must open a specific post in the app. On iOS — Universal Links (apple-app-site-association on server + NSUserActivityTypes). On Android — App Links (assetlinks.json + intent-filter). If the app is not installed — fallback to web version. More about deep linking.
Apple App Store Review Guidelines (Section 4.2) and Google Play Console require correct deep link implementation to avoid rejection.
Comparison: Internal Repost vs External Sharing
| Aspect | Internal Repost | External Sharing |
|---|---|---|
| Purpose | Publish in own feed | Send to another app |
| Deep link | Not required | Mandatory |
| Counter | Yes, increment/decrement | Not needed |
| iOS | Core Data + SwiftUI | UIActivityViewController |
| Android | Room + Jetpack Compose | Intent.ACTION_SEND |
What's Included in the Work
- Data model design for repost (DB schema, API).
- Development of embedded card for feed (iOS/Android/Flutter).
- Integration with system share sheet and deep linking.
- Configuration of push notifications for reposts.
- Documentation and source code handover.
Stages of Work
- Analysis — choose reference-to-original model.
- Design — DB schema, REST/GraphQL API.
- Implementation — backend + client UI.
- Integration — external sharing + deep links.
- Testing — un-repost, original deletion, edge cases.
- Deployment — publish to App Store / Google Play.
Comparison: Custom Development vs Ready-made SDK
If you use a ready-made SDK (e.g., Branch.io), you get a quick start but become dependent on an external provider, increasing license costs and risks of blocking. Custom implementation gives full control and saves up to 50% at scales above 10K users.
Timeline and Cost
Internal repost with UI — 1-2 days. External sharing with deep link — another 1-2 days. Complete system with both modes — 2-3 days when developing platforms in parallel. Cost is calculated individually — contact us for an accurate estimate.
Common Implementation Mistakes
- Missing handling of original deletion — repost references a non-existent object.
- Ignoring Android
FileProvider— crash on Android 7+ when sharing images. - Forgetting
popoverPresentationControlleron iPad — app freezes.
Our team's experience — 10+ years in mobile development, over 50 projects implemented. Quality guarantee for each stage. Order repost system development today — contact us for a consultation!







