I opened App Store Connect one evening to ship a small fix, and there was a question on the age rating screen I had not seen before. Does your app have social media capabilities?
The apps I run as an indie developer are wallpaper apps and an ambient sound app. Nothing resembling a social network. My first instinct was to scroll past.
Then I stopped. The wallpaper app has a share sheet. It has a favorites list. Does that count? I could not answer the question with any confidence until I went back and read Apple's actual definition.
I did read it, saved my answers, and learned a few things on the way that I would rather you not learn the hard way — especially if you plan to ship a Rork-built app after September 2026.
Apple drew the line at reach, not at sharing
Apple defines a social media capability as the ability to redistribute, amplify, or interact with user-generated content. But there is a qualifier attached, and the qualifier is doing most of the work: through a social feed or similar discovery method that visibly spreads content to many users (Introducing Time Allowances).
So the test is not whether your app touches content other people made. The test is whether there is a path by which that content lands in front of strangers.
The question to ask is not "can users share?" but "does something a stranger made appear on another stranger's screen?"
Sorting my own screens with that reading made the decision far less murky. Here is how I grouped things. This is my reading rather than an Apple ruling, so if you have something genuinely borderline, asking App Review is the safer path.
| Feature | My reading | Why |
|---|---|---|
| OS share sheet, one recipient at a time | Likely not | One receiver, no in-app path that spreads it |
| Favorites stored only on the device | Likely not | No user-generated content from anyone else |
| A list of posts from other users | Yes | That is the discovery method itself |
| Public comments or replies on posts | Yes | The interaction is visible to other readers |
| A trending or top-rated list of user uploads | Yes | It functions as amplification |
| A contact form that only reaches you | Likely not | Nothing reaches other users |
The category you picked in App Store Connect has no bearing on this. Utilities, Photo & Video, anything — if it has a feed, it lands in the same bucket.
Answering yes sets your floor at 13+
This is the part that made me take the question seriously.
An app that declares social media capabilities goes into the Social Media Time Allowance category and receives a minimum age rating of 13+. However gentle your answers to the rest of the questionnaire are, this single item raises the floor.
Your product page also picks up a new Social Media content descriptor (Age rating questionnaire now includes social media questions), so there is a store-facing effect as well.
If you were thinking about bolting a small community feature onto an otherwise quiet app, that math is worth redoing. Adding one feature and raising your audience floor now happen in the same motion.
The under-13 option comes with an API attached
Apple does offer an alternative: you can declare that your app has social media capabilities but that they are disabled for anyone under 13. Choose that, and your app is excluded from the Social Media Time Allowance category for users under 13, and your rating is decided by the rest of the questionnaire — which leaves room for something below 13+.
There is a condition. If you take that option, Apple says you will need to use the Declared Age Range API, at a minimum, to check users' age ranges. For users 13 and above, you stay in the Social Media category regardless.
The option that looks like an escape hatch is the one that carries the implementation work. I had assumed it was a matter of moving a checkbox. It is closer to a commitment to build age checking into the app.
Reading age ranges from an Expo app
Standard Rork generates React Native through Expo, and there is an Expo module for exactly this. expo-age-range calls Apple's Declared Age Range on iOS and Google's Play Age Signals on Android (Expo AgeRange documentation).
Install it, and add the iOS entitlement up front. Forgetting the entitlement fails at the moment you call the API on device, which is a slow way to find out.
npx expo install expo-age-range{
"expo": {
"ios": {
"entitlements": {
"com.apple.developer.declared-age-range": true
}
}
}
}The call site has to absorb a platform difference: Android needs a separate consent step, iOS folds consent into the request itself.
import * as AgeRange from 'expo-age-range';
// Minimal shape when all you need to know is "under 13 or not".
// Thresholds must be at least 2 years apart, or the request is rejected.
export async function resolveAgeGate(): Promise<'under13' | 'over13' | 'unknown'> {
try {
// Returns true/false only on iOS 26.2+. null means "unknown", not "not regulated".
const eligible = await AgeRange.isEligibleForAgeFeaturesAsync();
if (eligible === false) {
// Skip the gate only when the OS explicitly says regulation does not apply.
return 'over13';
}
} catch {
// Treat a failure as unknown and fall through to the request below.
}
try {
// Android needs consent first. On iOS this resolves with null and we continue.
const status = await AgeRange.requestAgeSignalsAccessAsync();
if (status !== null && status !== 'SHARED') {
return 'unknown';
}
const range = await AgeRange.requestAgeRangeAsync({
threshold1: 13,
threshold2: 16,
threshold3: 18,
});
if (range.lowerBound === null) {
return 'unknown';
}
return range.lowerBound >= 13 ? 'over13' : 'under13';
} catch (error) {
// ERR_AGE_RANGE_USER_DECLINED, ERR_AGE_RANGE_NOT_AVAILABLE, and friends land here.
// A refusal is "unknown". It is not an adult.
return 'unknown';
}
}
// Expected results
// child account under 13 -> 'under13'
// user declines to share -> 'unknown'
// not signed in to Apple account -> 'unknown'The iOS side needs a build from Xcode 26.0 or later, and simulator runtimes may not behave as expected. Verify on a real device. I nearly took a simulator result at face value and moved on.
On unsupported platforms, lowerBound comes back as 18
This is the one I would have walked straight into if I had skimmed.
On anything the API does not support — iOS earlier than 26, and web — requestAgeRangeAsync resolves with lowerBound: 18. That is the same value an adult produces. So the obvious gate opens for everybody on older devices.
// ❌ Everyone on an unsupported OS reads as 18 and passes
if (range.lowerBound >= 13) {
enableCommunityFeed();
}
// ✅ Open only when we confirmed the user is not under 13
const gate = await resolveAgeGate();
if (gate === 'over13') {
enableCommunityFeed();
} else {
// Both 'under13' and 'unknown' leave the feed closed.
disableCommunityFeed();
}Write the check as "confirmed not under 13", not as "13 or older". They sound identical until the answer is unknown, and only one of them fails closed.
isEligibleForAgeFeaturesAsync has the same shape. It resolves with null before iOS 26.2 and on Android, and null means unknown rather than unregulated. Treating it as false waves through exactly the users you were asked to check.
What I actually looked at, and what I answered
Once I had the definition straight, the work itself was small. I opened each app and counted the screens where content made by other people appears.
The wallpaper app has a share sheet and a favorites list that never leaves the device. There is no surface where user-uploaded images are listed. The ambient sound app is the same — no path by which someone else's recording reaches you. I counted, and saved "no" for both.
It was almost anticlimactic. What mattered more than the answer was writing down why I answered that way, with the screen names included. The next time this question comes around, or the day I decide a community feature is worth building, I can see in one line what needs re-examining.
Every time a store requirement changes, the expensive part has never been the implementation. It is going back through every app already shipped and bringing its metadata up to date. This question follows that pattern: starting September 2026, an answer is required to submit updates, not just new apps, and the same applies to notarization for alternative distribution. Meeting this question for the first time on a day you only wanted to ship a bug fix is not a good afternoon.
If you are publishing for the first time, the Apple-side steps you still have to do yourself before shipping a Rork app covers the neighboring ground. For declarations at submission time, auditing a Rork-generated Expo app's Privacy Manifest down the SDK chain is the closest companion, and if you do get sent back, the field guide to App Store rejections on Rork-built apps is where I would start.
Open the age rating screen in App Store Connect and read the new question. Before you save an answer, count once — which screens in your app put something a stranger made in front of another stranger? Those few minutes were what removed the guesswork for me.