new-term-radar
Daily radar for new AI terms: names of new models, products and repos, caught on X, Hugging Face, GitHub and sitemaps before keyword tools list them.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Dashboard de un solo dueño para métricas, comentarios, publicación y recomendaciones de Instagram, Facebook y TikTok. Todo funciona sin ninguna API de pago (ver "Restricción clave" más abajo) — la única excepción opcional es Claude para 3 funciones puntuales de IA en /recommendations, apagadas por default. Stack: Next.js 16 (App Router) + TypeScript + Supabase (Postgres/Auth/Storage) + Tailwind CSS v4 + Recharts. Desplegado en Vercel (plan Hobby); sync por GitHub Actions (Vercel Hobby limita el cron nativo a 1x/día).檢視完整 README ↗
Dashboard de un solo dueño para métricas, comentarios, publicación y
recomendaciones de Instagram, Facebook y TikTok. Todo funciona sin
ninguna API de pago (ver "Restricción clave" más abajo) — la única
excepción opcional es Claude para 3 funciones puntuales de IA en
/recommendations, apagadas por default.
Stack: Next.js 16 (App Router) + TypeScript + Supabase (Postgres/Auth/Storage) + Tailwind CSS v4 + Recharts. Desplegado en Vercel (plan Hobby); sync por GitHub Actions (Vercel Hobby limita el cron nativo a 1x/día).
ANTHROPIC_API_KEY el dashboard funciona igual: /recommendations
muestra un aviso de "función de IA desactivada" en vez de un error técnico,
y el resto (mejor horario/formato calculado en TS, alertas, reportes,
clasificación de comentarios) no depende de eso en absoluto.Todas las fases están implementadas en código. Lo que no está hecho
todavía es probarlas contra cuentas reales de Meta/TikTok y un proyecto de
Supabase real — eso requiere que completes el setup de la sección 1 y
corras las migraciones nuevas (0009 a 0013).
brands)./api/sync, un provider por red
(Instagram/Facebook/TikTok), GitHub Actions cada hora (+ historias cada
hora, comentarios cada 30 min)./analytics)./comments) con clasificación
por reglas (sentimiento + intención de compra, sin IA — ver
lib/analytics/comment-classify.ts), respuesta individual y masiva./reports, por plantilla de string (sin IA),
generado por cron los lunes./whatsapp, bandeja de lectura/respuesta manual vía
WhatsApp Cloud API (sin auto-respuesta)./calendar, publicación real a Meta/
TikTok con soporte de carrusel y fan-out a varias cuentas a la vez.⚠️ Los nombres de métricas de insights de la Graph API de Meta (lib/meta/instagram.ts,
lib/meta/facebook.ts) están escritos contra Graph API v22.0 (META_GRAPH_API_VERSION
en .env.local, no bajar de esa versión), pero no se han probado contra cuentas reales
todavía — Meta cambia estos nombres con cierta frecuencia. Si /api/sync devuelve
métricas vacías para una cuenta, revisa los console.warn del log (los insights fallan
de forma no fatal) y ajusta las listas de métricas contra
Graph API Explorer.
Dos cosas ya manejadas explícitamente por el código:
impressions/video_views deprecados: Instagram unificó todo en la métrica
views (posts, reels e historias); lib/platforms/instagram.ts la mapea a la
columna impressions de content_metrics. Facebook no tiene un views unificado
documentado — se dejó post_impressions_unique (reach) como base y
post_video_views solo para posts de video; verifícalo contra una Page real.checkEngagementEligibility lo detecta una vez
por cuenta antes de pedir insights (evita llamadas que sabemos que van a fallar) y
loguea un warning claro; el sync sigue guardando conteos básicos (likes/comments del
endpoint de media) en vez de fallar.npm install
cp .env.local.example .env.local
Rellena .env.local:
| Variable | De dónde sale |
|---|---|
NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY | Supabase → Project Settings → API |
META_APP_ID, META_APP_SECRET | Ya los tienes (Meta for Developers) |
META_TOKEN_ENCRYPTION_KEY | Generar con node -e "console.log(require('crypto').randomBytes(32).toString('base64'))" |
NEXT_PUBLIC_APP_URL | http://localhost:3000 en local |
SYNC_CRON_SECRET | Cualquier string aleatorio (protege /api/sync) |
ANTHROPIC_API_KEY, ANTHROPIC_MODEL | Fase 4 — console.anthropic.com; modelo por defecto claude-sonnet-5 |
Corre la migración en tu proyecto de Supabase:
npx supabase link --project-ref <tu-project-ref>
npx supabase db push
(o pega el contenido de supabase/migrations/0001_init.sql directamente en
el SQL Editor del dashboard de Supabase).
No hay registro público por diseño — es un dashboard de un solo dueño.
Crea tu usuario desde Supabase → Authentication → Users → "Add user"
(email + password), y usa esas credenciales en /login.
La Redirect URI configurada en Meta debe ser exactamente:
http://localhost:3000/api/auth/callback/meta
En producción, agrega también https://tu-dominio.vercel.app/api/auth/callback/meta
y actualiza NEXT_PUBLIC_APP_URL en Vercel.
Permisos (scopes) que pide el flujo: pages_show_list,
pages_read_engagement, pages_manage_metadata, read_insights,
instagram_basic, instagram_manage_insights. Tu app de Meta debe tener
acceso aprobado a estos (o estar en modo desarrollo con tu propio usuario
como tester, que es suficiente para empezar).
npm run dev
/settings/accounts creas un "negocio" (brands)./api/auth/meta/start?brand_id=... guarda
un nonce anti-CSRF en una cookie y redirige al login de Meta./api/auth/callback/meta con un code. El servidor:
/me/accounts),oauth_sessions./settings/accounts/select, donde eliges qué Pages
pertenecen a ese negocio.accounts, con el token ya cifrado. oauth_sessions se borra (uso único).Puedes repetir el flujo por cada negocio/Page que quieras conectar.
POST /api/sync?account_id=<uuid>&scope=all|stories sincroniza una cuenta
por llamada — así cada invocación cabe cómoda en el timeout de 10s de
Vercel Hobby sin importar cuántas cuentas tengas. GET /api/sync/accounts
lista las cuentas activas para que el caller sepa a quién llamar. Ambos
requieren Authorization: Bearer $SYNC_CRON_SECRET.
scope=all (default): posts/reels + audiencia.scope=stories: solo historias activas — pensado para un cron más
frecuente, porque expiran a las 24h.Vercel Hobby limita el cron nativo a 1x/día, así que .github/workflows/sync.yml
ya está armado para correr desde GitHub Actions: sync completo cada 4h +
sync de historias cada hora. Para activarlo:
APP_URL → tu dominio de Vercel (ej. https://social-pulse.vercel.app)SYNC_CRON_SECRET → el mismo valor que pusiste en Vercel/): seguidores totales, contenido publicado, engagement
promedio, crecimiento de seguidores y comparativa de engagement por red —
con filtros por negocio y por red./content): galería de posts/reels/historias con
miniatura, tipo y fecha./content/[id]): métricas actuales + evolución en el tiempo
(un punto por snapshot de /api/sync) + métricas específicas del tipo
(ej. taps_forward/exits en historias).Todo esto queda vacío hasta que corra el primer sync — los estados vacíos te lo indican explícitamente en vez de mostrar ceros engañosos.
En /recommendations, elige un negocio y presiona "Generar recomendaciones".
El botón:
recommendations (kind
best_time / top_format).ANTHROPIC_API_KEY está configurada, le pasa tus posts históricos
con mejor desempeño a Claude (lib/anthropic/client.ts) y le pide 5
ideas de contenido nuevas, guardadas como kind=content_idea.Sin contenido sincronizado con métricas, no hay suficiente data para calcular nada — el mensaje vacío te lo recuerda.
Bandeja en /whatsapp para leer y responder mensajes de WhatsApp Cloud
API a mano — sin auto-respuesta en esta fase.
Costo: recibir mensajes y responder dentro de la ventana de servicio de 24h (desde el último mensaje que te escribió el contacto) es gratis e ilimitado. Solo cuestan las plantillas de marketing/proactivas, que acá no se usan — este flujo es 100% gratis.
WHATSAPP_PHONE_NUMBER_ID y podés probar
con el número de prueba que da Meta (o agregar tu número de negocio
verificado más adelante).WHATSAPP_BUSINESS_ACCOUNT_ID) está
en la misma pantalla.whatsapp_business_messaging
sobre tu WhatsApp Business Account → generá el token desde ahí (el
token temporal de la consola de desarrollo expira en 24h, no sirve
para producción).<NEXT_PUBLIC_APP_URL>/api/webhooks/whatsappWHATSAPP_WEBHOOK_VERIFY_TOKEN.messages..env.local (y en Vercel para producción)./whatsapp.Desde /calendar, el botón "Publicar a varias redes" adjunta un
video (o varias imágenes para carrusel) y un texto una sola vez, y los
publica a todas las cuentas que marques (tus Instagram, Facebook y
TikTok conectados), cada una de forma independiente:
content_calendar por cuenta destino, todas
agrupadas por post_group_id. Si una red falla, las demás no se ven
afectadas — el panel muestra el estado de cada una por separado.startPublish/pollPublishStatus
de siempre (una cuenta por invocación, sigue cabiendo en el timeout de
Vercel Hobby), disparadas todas en paralelo desde el navegador.CAROUSEL con un child container por imagen; Facebook sube cada foto
sin publicar (published=false) y las adjunta a un post con
attached_media; TikTok usa el modo foto de la Content Posting API
(mismo flujo de borrador/inbox que el video). Un carrusel es siempre
de imágenes — no se puede mezclar con video.⚠️ El modo foto de TikTok (media_type: "PHOTO" en la Content Posting
API) está implementado según la documentación pública, pero no se probó
contra una cuenta real — mismo caveat que el resto de la integración de
TikTok en este proyecto. Verificalo contra la documentación viva antes de
depender de él en producción.
⚠️ Numeración aparte a propósito: las "Fases" de las secciones 1-6 de
arriba son las del build original de este proyecto. Esta sección es de
un rediseño posterior (rama feature/composio-v2) que reemplaza el
sistema de diseño y migra la integración de IG/FB/TikTok a
Composio — su propio plan de fases (Fase 0 =
diseño, Fase 1 = esto) es independiente del de arriba.
Qué es esto y qué no es todavía: src/lib/social/* es un motor de
integración nuevo que corre en paralelo a la integración directa
actual (src/lib/meta/*, src/lib/tiktok/*, src/lib/platforms/*) —
no la reemplaza ni la toca. Se retira código directo solo cuando su
equivalente en Composio queda verificado, cuenta por cuenta, no de una.
COMPOSIO_API_KEY a .env.local (y a Vercel para producción)
— server-side únicamente, nunca se expone al cliente./settings/composio, elegí un negocio y conectá Instagram/
Facebook con el botón — Composio maneja el OAuth con su propia auth
administrada, no hace falta credenciales propias de Meta para esto.TIKTOK_CLIENT_KEY/TIKTOK_CLIENT_SECRET,
las mismas que ya usa la integración directa). El código para crear
ese auth config por API existe (getOrCreateTikTokAuthConfig en
lib/social/connections.ts) pero el nombre exacto de los campos de
credenciales no está verificado contra la API real de Composio
todavía — antes de confiar en él, probalo con tu API key real o
armá el auth config una vez a mano en el dashboard de Composio
(Toolkits → TikTok → Configure) e inspeccioná el payload que arma esa
UI para confirmar los nombres de campo./settings/composio trae analíticas de Instagram en vivo vía
Composio (perfil, alcance/interacciones de los últimos 7 días, últimas
publicaciones) — el proof of concept de la Fase 1. Reutiliza
ProviderContentItem (lib/platforms/types.ts) como shape de salida,
así que cuando esto reemplace al sync directo (Fase 3 del plan de
Composio) el resto de la app no debería tener que cambiar.
composio_connections (migración 0015) mapea cada cuenta conectada
por Composio a un negocio — tabla nueva, separada de accounts (la de
la integración directa) a propósito: así ninguna migra hasta que se
decida moverla, y nada de lo existente (sync, calendario, comentarios)
se ve afectado mientras tanto.
El shape exacto de @composio/core (composio.tools.execute(slug, {userId, connectedAccountId, arguments}), composio.connectedAccounts. link(...), composio.authConfigs.create(...)) se confirmó leyendo el
código fuente TypeScript que se instala con el paquete
(node_modules/@composio/core/src/), no adivinado ni copiado de docs
scrapeadas — la documentación pública no fue 100% consistente entre sí
en algunos puntos durante la investigación. Los slugs de tools
(INSTAGRAM_GET_USER_INFO, INSTAGRAM_POST_IG_USER_MEDIA,
FACEBOOK_CREATE_MULTI_PHOTO_POST, etc.) se verificaron contra el
catálogo real de Composio, no contra la lista original del brief (que
tenía al menos un slug con nombre incorrecto —
INSTAGRAM_CREATE_MEDIA_CONTAINER no existe, es
INSTAGRAM_POST_IG_USER_MEDIA).
⚠️ composio.connectedAccounts.initiate() está deprecado — devuelve
400 en el backend real ("no longer supported... Use POST
/api/v3/connected_accounts/link instead") pese a que el propio código
fuente del SDK todavía lo expone y documenta como si fuera el método
vigente. Se descubrió probando en vivo contra una API key real, no leyendo
el código — usá composio.connectedAccounts.link() (mismo shape de
retorno, mismo allowMultiple), que es lo que usa
initiateComposioConnection en settings/composio/actions.ts. Ojo si en
el futuro se lee la SDK de nuevo: el código fuente por sí solo no alcanza
para saber qué endpoints retiró el backend.
Otra cosa importante que costó encontrar: Composio tiene productos
separados bajo el mismo login — "Connect" (dashboard.composio.dev,
para conectar tus propias apps de IA a un MCP, con su propio tipo de
key) y "Platform" (Build agents with the Composio SDK, con API keys de
proyecto, no de organización — la página de tokens de organización
literalmente dice "if you are looking for API keys go to project
settings"). @composio/core necesita la de Platform → Project → API
Keys específicamente. Si conectaste cuentas antes vía "Connect" (o vía
un MCP de Composio ya autenticado en otra herramienta), esas conexiones
NO aparecen bajo el proyecto de Platform — son namespaces distintos.
Dos cosas que no son bugs de este código, sino límites reales del
acceso actual a la API de TikTok (Login Kit + Content Posting API, scopes
user.info.profile, user.info.stats, video.list):
research.data.*), que es un
programa aparte con aprobación separada para investigadores, no algo
que se habilite en un Login Kit normal. tiktokProvider.fetchComments
queda sin implementar a propósito — la UI (/comments con filtro
TikTok, y el detalle de contenido de una pieza de TikTok) avisa esto en
vez de mostrar una bandeja vacía sin explicación.video.list (Display API) solo devuelve
cover_image_url (portada) y share_url (permalink a la app de
TikTok) — no hay una URL de archivo de video descargable/embebible con
estos scopes. El dashboard en general tampoco reproduce video de
ninguna red (solo miniatura + link "Ver original"), así que esto es
consistente con Instagram/Facebook, pero en TikTok es más notorio
porque no hay alternativa de reproducir inline en absoluto.
cover_image_url es una URL firmada por TikTok que expira
a los pocos días — por eso el sync ahora la descarga y la sube a
Supabase Storage al momento de sincronizar (ver
cacheRemoteThumbnail en src/lib/supabase/storage.ts, llamado desde
src/app/api/sync/route.ts), guardando
esa copia estable en thumbnail_url en vez de la URL firmada. Si el
caching falla (por la razón que sea), cae de vuelta a la URL de
TikTok tal cual — mejor una miniatura que puede expirar más adelante
que ninguna.Si en el futuro TikTok aprueba un producto/scope con acceso a comentarios
o a un archivo de video real, fetchComments/mediaUrl en
src/lib/platforms/tiktok.ts son los puntos de extensión — seguí el
mismo contrato (ProviderComment[], ProviderContentItem.mediaUrl) que
usan Instagram y Facebook.
src/
├── app/
│ ├── (auth)/login/ # login del dueño
│ ├── (dashboard)/ # shell con sidebar + rutas del dashboard
│ │ ├── settings/accounts/ # gestión de negocios y cuentas conectadas (integración directa)
│ │ ├── settings/composio/ # conexiones + proof of concept del motor Composio (en paralelo)
│ │ ├── content/ # galería + detalle de contenido
│ │ ├── analytics/ # heatmap de horario, formato, comparador de cuentas
│ │ ├── comments/ # bandeja centralizada de comentarios
│ │ ├── calendar/ # calendario, publicación y fan-out multi-red
│ │ ├── recommendations/ # motor de recomendaciones
│ │ ├── reports/ # reportes semanales por plantilla
│ │ └── whatsapp/ # bandeja de WhatsApp Cloud API
│ └── api/
│ ├── auth/{meta,tiktok}/start/ # inicia OAuth
│ ├── auth/callback/{meta,tiktok}/ # recibe el callback
│ ├── sync/ # sync de métricas (+ /accounts para listar)
│ ├── reports/weekly/ # genera los reportes semanales (cron)
│ ├── webhooks/whatsapp/ # webhook de WhatsApp Cloud API
│ └── media/[...path]/ # proxy de dominio verificado para TikTok
├── components/
│ ├── ui/ # primitivos de UI
│ ├── charts/ # wrappers de Recharts con el theme del proyecto
│ └── dashboard/ # componentes del dashboard
├── lib/
│ ├── supabase/ # clientes server/browser/admin + storage
│ ├── meta/ # llamadas crudas a la Graph API (oauth, IG, FB)
│ ├── tiktok/ # llamadas crudas a la API de TikTok
│ ├── whatsapp/ # WhatsApp Cloud API (envío, ventana de 24h, queries)
│ ├── platforms/ # interfaz PlatformProvider (instagram/facebook/tiktok)
│ ├── social/ # motor Composio (client, instagram, connections) — en paralelo
│ ├── analytics/ # agregaciones (engagement, queries, recomendaciones,
│ │ # clasificación de comentarios, alertas, reporte semanal)
│ ├── anthropic/ # integración con la API de Claude (opcional)
│ └── crypto.ts # cifrado AES-256-GCM de tokens
└── types/db.ts # tipos de la base de datos
supabase/migrations/ # 0001 a 0013, numeradas y secuenciales
.github/workflows/
├── sync.yml # sync de métricas/historias/comentarios
└── weekly-report.yml # reportes semanales (lunes)
brands agrupa cuentas; cada account pertenece a un
negocio y a una red (platform). Filtrar "por negocio" = filtrar por
brand_id; filtrar "por red" = filtrar por platform.platform correspondiente y se implementa
PlatformProvider (ver src/lib/platforms/{instagram,facebook,tiktok}.ts
como ejemplo), registrándolo en src/lib/platforms/index.ts. Las 3 redes
actuales ya siguen este patrón.content) tiene snapshots de
métricas con fecha (content_metrics), nunca se sobreescriben — así se
puede graficar la evolución en el tiempo de cualquier post/reel/historia.src/lib/crypto.ts). La clave vive solo en variables de entorno.force-dynamic: leen datos por
sesión/usuario, así que nunca se sirven cacheadas entre distintos
visitantes ni se congelan en el snapshot del build.