Saltar al contenido
Volver a proyectos

Verificación de Publicaciones en Instagram con Visión Artificial

Verificación de Publicaciones en Instagram con Visión Artificial

Resumen

La plataforma nació para cerrar la distancia entre lo que una marca de eventos pide a sus RRPP y lo que realmente pasa en Instagram. La app permite crear marcas, eventos, tareas y asignaciones; el sistema verifica cada Historia con visión por computador y reporta el cumplimiento en tiempo real, sin perseguir a nadie por mensajería.

2
Apps en producción
35
Políticas RLS activas
AES-256
Cifrado de sesiones

El Problema

Las marcas de eventos nocturnos dependen de equipos de RRPP que deben publicar el material oficial en Instagram, pero no existía forma automática de saber si lo habían hecho de verdad. Confiar en un «sí, ya lo subí» bastaba para perder trazabilidad, dejar sin medir el cumplimiento y aceptar que la promoción quizá no estaba pasando. Tampoco había manera de distinguir a un RRPP cumplidor de uno que simplemente ignoraba la tarea.

La Solución

Plataforma multi-app con verificación visual automática. Una app móvil para gestores de marca, un dashboard web operativo, un backend Supabase con RLS estricta y dos microservicios Python: uno compara cada Historia de Instagram contra el cartel oficial usando embeddings del modelo SSCD (ResNet50), y otro monitoriza cuentas con sesiones cifradas y fingerprint de dispositivo para no caer en baneos en cadena.

Producto en uso

Capturas reales de web y móvil

Las capturas conectan la explicación con el producto real: el dashboard con KPIs, el login en sus dos formatos, la gestión de RRPP con invitación reutilizable y la pantalla de tareas con el cumplimiento por evento.

01

Dashboard web con 4 KPIs

La imagen muestra el panel principal con cumplimiento medio, Historias verificadas en 7 días, RRPP activos y alertas. Es la vista que abre la web y la que mejor resume el estado operativo de una marca de un vistazo.

02

Login de escritorio con doble rol

El login web separa Empresa y RRPP con una pestaña segmentada y refuerza la identidad con fondos de evento. La idea es que la herramienta se sienta hecha por y para gente que trabaja en este sector.

03

Gestión de RRPP e invitaciones

Aquí se ve la tabla con el cumplimiento por RRPP, el alcance y los enlaces de invitación reutilizables. La empresa controla quién está dentro, cómo va cada uno y cómo invitar a uno nuevo sin escribir un email.

04

Tareas con vista de tarjetas y tabla

La pantalla de tareas muestra el diseño oficial como referencia, el porcentaje de cumplimiento por tarea y filtros por marca, evento, fecha y tipo de contenido. La empresa ve de un vistazo lo que se ha pedido y lo que se ha entregado.

Mobile-first

Pensada para el móvil desde el primer día

La versión que más se usa es la del teléfono. La app móvil está construida con React Native y Expo Router, con la sesión guardada en el dispositivo y el mismo branding que la web. El dashboard web es totalmente responsive, pero el objetivo es que el gestor de marca pueda crear eventos, asignar RRPP y revisar el cumplimiento desde el móvil, en el propio evento.

  • App móvil con React Native + Expo Router y sesión persistida en el dispositivo.
  • Web responsive: el dashboard y los formularios se adaptan a cualquier pantalla.
  • Próximo paso: publicarla como app nativa de iOS en la App Store.

Herramientas

Qué utilicé y por qué

Elegí herramientas que me permitieran entregar dos apps, un backend robusto y servicios de IA sin pagar infraestructura cloud durante el desarrollo.

Expo y React Native

Base de la app móvil. Expo Router para las rutas, Reanimated para las microinteracciones y expo-image para portadas y logos sin cachés rotas.

Next.js 14

Dashboard web con App Router, Server Components para los listados y Route Handlers para los endpoints de OAuth, monitor y WhatsApp.

Supabase y PostgreSQL

Backend gestionado: Auth, Postgres con RLS, Storage para logos y portadas, y Realtime para refrescar los KPIs. 21 tablas, 6 vistas y 35 políticas activas.

PyTorch y ResNet50 (SSCD)

Microservicio Python con FastAPI que envuelve el modelo SSCD de Facebook AI Research. Convierte cada Historia en un vector de 512 dimensiones y devuelve la similitud coseno frente al cartel oficial.

instagrapi con fingerprint

Microservicio Python que monitoriza las Historias desde una cuenta dedicada. La sesión se guarda cifrada con AES-256-GCM y cada cuenta lleva su proxy y su propio dispositivo Android para evitar baneos en cadena.

Docker y Turborepo

Monorepo con pnpm + Turborepo para que web y móvil compartan tipos, queries y design tokens. Los microservicios Python viven en docker-compose con healthcheck y volúmenes persistentes.

Funcionalidades

Qué incluye el producto

Lo que esta plataforma resuelve de verdad no es mostrar KPIs, sino cerrar el ciclo entre lo que se pide, lo que se publica y lo que se puede demostrar que se hizo.

01

Verificación visual de Historias

Cuando un RRPP sube una Historia, el sistema la descarga, calcula un embedding con SSCD y la compara con el cartel oficial. Si la similitud supera el umbral, la tarea pasa a completada sin que nadie tenga que aprobarla a mano.

02

Login con doble rol

Una sola app con dos entradas: Empresa para los dueños de marca y RRPP para los invitados por enlace. La sesión se mantiene en el dispositivo y la interfaz cambia según el rol detectado en el JWT.

03

Onboarding visual multipaso

El primer ingreso guía paso a paso: alta de empresa, alta de marca con logo y género musical, alta de evento con portada, fecha y dirección geocodificada. Cada paso previsualiza el resultado antes de confirmar.

04

Dashboard con 4 KPIs en vivo

Cumplimiento medio, Historias verificadas en los últimos 7 días, RRPP activos y alertas abiertas. Los números se calculan desde vistas SQL agregadas y se refrescan con pull-to-refresh sin recargar la app.

05

RRPP con invitación reutilizable

La empresa genera un enlace, lo comparte y el RRPP se da de alta cuando entra. La invitación caduca a los 30 días, no exige email previo y captura el opt-in de WhatsApp en el mismo formulario.

06

Tareas auto-asignadas

Crear una tarea dispara un trigger en PostgreSQL que genera una asignación por cada RRPP activo del evento. Asignar un RRPP nuevo a un evento existente le crea sus tareas de forma idempotente, sin duplicados.

Proceso

Cómo lo construí

El proyecto fue creciendo capa a capa: primero el modelo de datos y la autenticación, después la web, luego la app móvil y, al final, los microservicios que justifican el nombre del producto.

01

Definí el modelo multi-tenant

Empecé por las tablas y las relaciones: empresa, marca, evento, RRPP, tarea, asignación y verificación. Decidí desde el principio que cada consulta debía pasar por RLS, sin excepciones para el backend.

02

Monté Supabase y las políticas RLS

Levanté el proyecto en Supabase Cloud, definí 21 tablas, las vistas agregadas para los KPIs y las 35 políticas RLS. Aquí apareció la primera recursión y tuve que extraer subconsultas a funciones SECURITY DEFINER.

03

Construí el dashboard web

Next.js con App Router para el panel de gestión: dashboard, marcas, eventos, RRPP, tareas y configuración. Login con email y contraseña, y OAuth de Google y Apple marcados como «próximamente» para no romper el flujo principal.

04

Desarrollé la app móvil

Expo con Expo Router para la app del gestor de marca. Login con pestaña Empresa/RRPP, onboarding de marca y evento en dos pasos, dashboard con 4 KPIs y pantalla de ajustes. Los tabs de Equipo, Eventos y Alertas son stubs por ahora.

05

Entrené el verificador visual

Levanté el microservicio SSCD con PyTorch y ResNet50, expuse /embed y probé con carteles y capturas reales. Los umbrales quedaron en 0,5 para éxito, entre 0,4 y 0,5 para warning y por debajo de 0,4 para alerta.

06

Cerré el monitor de Instagram

El microservicio instagrapi se encarga de iniciar sesión con cookies cifradas, mantener un fingerprint Android por cuenta y descargar las Historias de los candidatos para que el verificador las compare.

Dudas y decisiones

Problemas que tuve que resolver

Las decisiones importantes no fueron tecnológicas, sino operativas: qué cuenta vigila a qué cuenta, cómo demostrar el cumplimiento sin caer en baneos y cómo separar lo público de lo privado.

Verificar Historias de cuentas privadas

Meta no expone las Historias de cuentas privadas por la Graph API. La salida fue monitorizar desde una cuenta dedicada, cifrar la sesión y descargar el media por debajo para que el verificador pudiera trabajar.

Evitar baneos en cadena

Instagram penaliza rápido los patrones repetidos. Cada cuenta monitorizada lleva su propio proxy, un fingerprint Android único y una cadencia aleatoria de 40 a 120 minutos para no parecer un bot.

RLS sin recursiones

El primer intento de políticas caía en recursión infinita al cruzar empresa, marca y evento. Lo solucioné extrayendo cada cruce a una función SECURITY DEFINER y llamándola desde las políticas.

Auto-asignación sin duplicados

Una tarea nueva debía asignarse a todos los RRPP activos y un RRPP nuevo debía recibir las tareas ya creadas. Lo resolví con ON CONFLICT en el trigger para que ambas direcciones sean idempotentes.

Dos apps, un solo backend

Web y móvil no podían divergir en tipos ni en queries. Lo moví todo a un monorepo con paquetes compartidos: types, supabase-queries y design tokens. La web va en React 18 y la app ya corre en React 19.

Costes de inferencia bajo control

El modelo SSCD pesa alrededor de 110 MB y cada comparación cuesta GPU. Cacheé el embedding del cartel oficial y limité el número de candidatos por ejecución para que el coste no escale con cada RRPP.

Arquitectura

Cómo está construido

La arquitectura separa apps, backend gestionado y microservicios Python, con tipos y queries compartidos en el monorepo para que web y móvil nunca diverjan.

1

App móvil Expo con Expo Router, Supabase JS y AsyncStorage para la sesión offline. Comparte tipos con el dashboard y consume las mismas funciones de Supabase.

2

Dashboard web en Next.js 14 con App Router, React Hook Form y Zod para los formularios. El middleware de Supabase SSR protege las rutas privadas antes de renderizar.

3

Supabase como backend: Postgres con 21 tablas, 6 vistas agregadas, 35 políticas RLS, Storage para logos y portadas, y Auth con email y OAuth pendiente de aprobación.

4

Microservicio SSCD en Python con FastAPI y PyTorch. Carga el modelo ResNet50 + GeM entrenado por Facebook AI Research, expone /embed y devuelve vectores L2-normalizados para comparar.

5

Microservicio IG Monitor en Python con instagrapi. Mantiene una cuenta dedicada por empresa, cifra la sesión con AES-256-GCM y descarga las Historias por candidato para que SSCD las verifique.

6

docker-compose levanta los dos microservicios con healthcheck y volúmenes para modelos y sesiones. El monorepo pnpm + Turborepo coordina web, móvil y los paquetes compartidos.

Modelo de datos

Multi-tenant con RLS de extremo a extremo

21 tablas y 6 vistas agregadas, todas detrás de RLS sobre auth.uid(). Estas son las piezas que mejor explican el modelo.

profiles · identity

Usuarios y su rol (empresa o RRPP), con su handle de Instagram. Cada política de RLS se evalúa contra auth.uid().

id (auth.uid)roleinstagram_handle
marcas · eventos

La marca (con sus sectores musicales y logo) y el evento (portada, fecha y dirección geocodificada) que cuelga de ella.

marcas.owner_idmarcas.sectoreseventos.marca_ideventos.fecha
event_rrpp

Asignación de un RRPP a un evento, con invitación reutilizable y removed_at para gestionar las bajas sin borrar el histórico.

event_iduser_idremoved_atinvite_token
tasks · task_assignments

Tarea con su media de referencia (cartel o vídeo) y una asignación por cada RRPP activo, generada automáticamente por trigger.

reference_media_urlreference_media_typeUNIQUE(task_id, user_id)status
story_verifications

Verificación de cada Historia contra la referencia: similitud, fuente y monitor que la capturó.

similaritysourcemonitor_idstatus
instagram_monitor_sessions

Sesión de la cuenta que monitoriza, cifrada con AES-256-GCM, con su proxy e intervalo de sondeo aleatorio.

encrypted_sessionproxyintervaldevice_fingerprint

Contrato de API

El microservicio de verificación

El servicio SSCD es un FastAPI aislado, protegido por un secreto de servicio, que la web consume para verificar imágenes y vídeos.

GET/health

Healthcheck del microservicio para el healthcheck de docker-compose.

POST/embed

Recibe una imagen y devuelve su embedding de 512 dimensiones.

auth: X-Service-Secret

POST/video/embed

Extrae fotogramas de un vídeo y devuelve un fingerprint multi-frame.

auth: X-Service-Secret

POST/video/match

Compara un vídeo candidato contra un fingerprint de referencia y devuelve las métricas de coincidencia.

auth: X-Service-Secret

Stack Tecnológico

Tecnologías utilizadas

React NativeExpoExpo RouterTypeScriptReanimatedNext.js 14Tailwind CSSReact Hook FormZodSupabasePostgreSQLRow-Level SecuritySupabase StoragePythonFastAPIPyTorchResNet50 (SSCD)instagrapiDockerTurborepoAES-256-GCM

¿Tienes una marca con equipo de RRPP?

Esta plataforma resuelve exactamente eso: trazabilidad real, cumplimiento medible y verificación visual sin perseguir a nadie por mensajería.