Hola. Me llamo Ayumu Kitabayashi, vivo en Japón y desarrollo por mi cuenta minulo, una app para iPhone que oculta los Reels de Instagram, los Shorts de YouTube y la pestaña "Para ti" de TikTok, sin tocar los mensajes directos. Está hecha con React Native y Expo.
Cuando empecé, di por hecho que la API de Tiempo en pantalla (Screen Time) me iba a resolver la mitad del trabajo. Resolvió una parte importante, pero no la que yo esperaba. Este artículo va de eso: qué hace esa API, dónde se acaba, y qué tres caminos quedan cuando quieres esconder solo una parte de una red social.
Lo que Tiempo en pantalla sí te da
Son tres frameworks que trabajan juntos:
- FamilyControls pide la autorización y muestra el selector donde la persona elige apps, categorías o sitios web.
- ManagedSettings aplica el bloqueo: pone un escudo (shield) sobre esas apps o esos dominios en Safari.
- DeviceActivity decide cuándo: horarios, intervalos, umbrales de uso.
Además puedes añadir dos extensiones: ShieldConfiguration, para cambiar el aspecto de la pantalla de bloqueo (textos, colores, botones), y ShieldAction, para decidir qué pasa al tocar esos botones.
En React Native no tienes que escribir todo esto desde cero; yo parto de la librería react-native-device-activity y le sumo código nativo propio. Eso sí: nada de esto corre en Expo Go. Necesitas expo-dev-client, build nativa y, para publicar, el entitlement de Family Controls aprobado por Apple.
Lo que no te da (y lo descubrí a golpes)
No entra dentro de otra app. El escudo cubre Instagram entero o no lo cubre. No hay forma de decir "deja abrir Instagram pero no la pestaña de Reels". Tampoco existe en iOS algo como los servicios de accesibilidad de Android, que leen la pantalla de otra app.
No sabes con certeza qué eligió la persona. El selector te devuelve tokens opacos, no nombres. En la extensión de la pantalla de bloqueo, a veces el sistema ni siquiera pasa el nombre de la app, así que mis textos tienen que funcionar también con el nombre vacío.
El botón del escudo no abre tu app. Desde ShieldAction intenté abrir el esquema de URL de minulo y no pasó nada: ni error, ni log útil. Lo que sí funciona es lanzar una notificación local y que la persona la toque. Son dos toques en vez de uno, y si la persona no dio permiso de notificaciones, el botón no puede hacer nada; en ese caso muestro solo "Cerrar".
ShieldConfiguration no puede escribir. Quise contar cuántas veces aparecía la pantalla de bloqueo guardando un número en el App Group desde esa extensión. Leer, sí; escribir, no: el sistema lo ignora sin avisar. El conteo terminó en ShieldAction.
Mientras la app está bloqueada, sus notificaciones tampoco llegan. Así lo decidí en minulo, y hay que decirlo claro en la interfaz. En minulo, bloquear la app oficial es gratis por un máximo de 2 horas cada vez.
Conclusión de esta parte: Tiempo en pantalla sirve para cerrar la puerta de la app oficial, no para editar lo que hay dentro. Para lo segundo hay que irse a la web.
La web es el único lugar donde se puede recortar
En instagram.com o youtube.com todo es HTML y CSS; un selector basta para ocultar un enlace o una sección. La decisión real es dónde se dibuja esa página y quién puede verla.
Forma 1: bloqueador de contenido de Safari
Le das a Safari una lista JSON de reglas (trigger y action) y él la compila. Tu código nunca corre en la página y no puede leerla. Es lo más respetuoso con la privacidad que existe en iOS.
[{
"trigger": { "url-filter": "^https://www\\.instagram\\.com/reels/" },
"action": { "type": "block" }
}]
Lo que me frenó, visto desde el lado de la API:
- La única acción de estilo es
css-display-none. Ocultar sí; desactivar un botón o redirigir a otra ruta, no. - El
url-filteracepta un subconjunto de regex sin alternancia (|). Cada variante es otra regla. - No tienes ninguna señal de vuelta. Si la red cambia sus clases, la regla deja de coincidir y nadie se entera. Y una clave que el formato no espera puede hacer que la lista entera se descarte, también en silencio. Por eso mi build valida que cada regla tenga exactamente esas dos claves antes de exportarla.
Forma 2: extensión web de Safari
Aquí sí corre tu JavaScript: puedes vigilar el DOM con MutationObserver, quitar el comportamiento de un botón o mandar /reels/ a la bandeja de mensajes.
A cambio, Safari le dice a la persona que la extensión puede leer la página, sitio por sitio. En una red social eso incluye sus conversaciones. Mi criterio sería mover a la extensión solo lo que de verdad no se puede escribir como selector.
Lo que comparten las dos formas de Safari
Ninguna toca la app oficial. La costumbre que la gente quiere cortar es tocar el ícono de Instagram sin pensar, y ese ícono no abre Safari. Pedirle a alguien que se acuerde de escribir la dirección en el navegador, justo en el momento de la tentación, es diseñar para una persona que no existe.
Forma 3: un WKWebView dentro de tu propia app
Es la que usa minulo, y es la única que se combina bien con Tiempo en pantalla. La app abre la web oficial de cada red con react-native-webview e inyecta su CSS y su JS; el inicio de sesión ocurre en la página de la propia red. Tiempo en pantalla bloquea la app oficial, y el escudo ofrece entrar en minulo. El ícono sigue llevando a algún sitio, pero ese sitio no tiene Reels.
El costo es que ahora el mantenimiento es tuyo. Lo que más me enseñó:
-
Dos momentos de inyección. Los estilos van en
injectedJavaScriptBeforeContentLoadedpara que nada se vea ni un instante; la lógica va después, con un observador, porque estas páginas siguen montando elementos durante toda la sesión. -
Las rutas cambian sin recargar. Son aplicaciones de una sola página: si una regla aplica solo en
/explore/, el script inyectado tiene que detectar el cambio de URL y activar o quitar su propio<style>. - Mide tus selectores. Cuento cuántos elementos encuentra cada regla. Una que se queda en cero durante varias visitas probablemente se rompió, aunque nada haya fallado.
-
No confíes en los mensajes de la página. Tu script y el de la red viven en el mismo contexto, así que cualquiera puede llamar a
window.ReactNativeWebView.postMessage. La app filtra por un token propio de cada pantalla y por una lista cerrada de tipos de mensaje, y lo trata como primera barrera, no como seguridad completa. - Un user agent coherente. El WebView declara la misma versión de Safari que tiene el teléfono, en lugar de una cadena vieja y fija que llama la atención.
Cómo elegiría hoy
- Solo computadora y la privacidad es lo primero: bloqueador de contenido, y nada más si se puede.
- Computadora, con necesidad de redirigir o desactivar: bloqueador más una extensión pequeña para lo que falte.
- iPhone: WKWebView en tu app, con Tiempo en pantalla cerrando la app oficial. Es la única forma que alcanza el ícono.
Para no tener que elegir una sola vez, en minulo las reglas se declaran en un solo archivo TypeScript (urlFilter, css, redirect) y de ahí pueden salir las tres formas. Cuando una salida interpretaba distinto que las otras, el error aparecía en un único lugar.
Si te interesa ver el resultado: minulo. Ocultar los Reels y los Shorts es gratis. Si estás peleando con Tiempo en pantalla en React Native, cuéntame en los comentarios en qué parte te trabaste.












