Plataforma

AI Digest semanal

Cada lunes, Iterar genera un resumen de una página por proyecto con los patrones que detectó la IA, el sentiment de la semana, los items que más crecieron y 3 acciones sugeridas. Se manda por mail al founder y queda en /dashboard/projects/[slug]/digests.

Cómo funciona

  • Una sola llamada a Gemini Flash por proyecto por semana (~1 cent / digest).
  • Idempotente: si ya hay un digest para esa semana y se envió, no se duplica.
  • Se omiten proyectos sin actividad en los últimos 7 días (skipped_reason = no_activity).
  • Honra user_profiles.preferred_language (es / en / pt) para el texto generado.
  • Si Resend falla, el digest queda guardado pero con delivered_at = null.

Endpoint

POST /api/ai/digest/run — protegido conAuthorization: Bearer $INTERNAL_API_TOKEN. Body opcional:

  • {} o vacío → corre para todos los proyectos en plan Starter/Pro/Studio.
  • { "project_id": "..." } → corre solo para ese proyecto.
  • { "force": true } → regenera aunque ya haya digest entregado.
  • { "include_free": true } → incluye proyectos del plan Free (mayormente útil en dev).
run all (cron)
bash
curl -X POST https://app.iterar.io/api/ai/digest/run \
  -H "Authorization: Bearer $INTERNAL_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
forzar single project
bash
curl -X POST https://app.iterar.io/api/ai/digest/run \
  -H "Authorization: Bearer $INTERNAL_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"project_id":"00000000-0000-0000-0000-000000000000","force":true}'

Programar el cron

Elegí la opción que mejor se lleve con tu stack. Recomendamos Mondays 12:00 UTC (≈ 9am ART, 7am MEX, 9am ESP).

Opción 1: Supabase Scheduled Function (pg_cron + pg_net)

Necesitás habilitar las extensiones pg_cron y pg_net desde Database → Extensions. Después seteá el token conalter database postgres set app.internal_api_token = '...'; y corré:

supabase.sql
sql
-- Supabase: pg_cron + pg_net (Database → Extensions)
select cron.schedule(
  'iterar-weekly-digest',
  '0 12 * * 1', -- Mondays 12:00 UTC (≈ 9am ART)
  $$
    select net.http_post(
      url := 'https://app.iterar.io/api/ai/digest/run',
      headers := jsonb_build_object(
        'Authorization', 'Bearer ' || current_setting('app.internal_api_token'),
        'Content-Type', 'application/json'
      ),
      body := '{}'::jsonb
    );
  $$
);

Opción 2: Cloudflare Cron Trigger

Un Worker mínimo:

wrangler.toml
toml
# wrangler.toml
name = "iterar-digest-cron"
main = "src/worker.ts"
compatibility_date = "2025-05-01"

[triggers]
crons = ["0 12 * * 1"]   # Mondays 12:00 UTC

[vars]
ITERAR_URL = "https://app.iterar.io/api/ai/digest/run"
# INTERNAL_API_TOKEN comes from `wrangler secret put INTERNAL_API_TOKEN`
src/worker.ts
ts
// src/worker.ts
export default {
  async scheduled(_event: ScheduledEvent, env: Env) {
    const res = await fetch(env.ITERAR_URL, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${env.INTERNAL_API_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: "{}",
    });
    if (!res.ok) {
      console.error("digest run failed", res.status, await res.text());
    }
  },
};

interface Env {
  ITERAR_URL: string;
  INTERNAL_API_TOKEN: string;
}

Opción 3: Vercel Cron

Si la app está en Vercel y el token vive en una env var del mismo proyecto, podés usar directamente Vercel Cron — pero ojo: tenés que validar el bearer del headerx-vercel-cron manualmente o autorizar el endpoint con un middleware. El esqueleto JSON:

vercel.json
json
// vercel.json
{
  "crons": [
    { "path": "/api/ai/digest/run", "schedule": "0 12 * * 1" }
  ]
}
Timeouts
El runner procesa proyectos en lotes de 5 en paralelo. Cada proyecto consume ~3–6s (Gemini + Resend). Si tenés 500+ proyectos, considerá dividir por franja horaria del owner o subir el maxDuration de la función.

Generación manual

Desde /dashboard/projects/[slug]/digests el founder puede tocar Generar ahora, que llama a la server action generateDigestNow(slug). Internamente usa la sesión del usuario para verificar ownership y después invoca deliverWeeklyDigest con force: true — no necesita el bearer token porque la acción se ejecuta del lado server con la service role key.

Costos
El digest se ejecuta gratis para el founder. Internamente usamos Gemini 2.5 Flash (≈ $0.0003 por digest) y un mail vía Resend. No descontamos créditos del balance del usuario para no penalizar la observabilidad.