# Manual de lanzamiento — admin avanzado

JobsWorld **no finge** APIs de Meta, LinkedIn ni X. Esas plataformas exigen App Review, Business Manager verificado y, en Meta, permisos `pages_manage_posts` que una app nueva no obtiene en el día 1. Lo que sí es **real hoy**:

| Qué | Cómo |
|-----|------|
| Composer nativo | Intents oficiales (share-offsite, tweet, t.me/share, wa.me, Facebook sharer, Threads, Reddit submit, mailto) |
| Telegram Bot | `sendMessage` si hay `TELEGRAM_BOT_TOKEN` + `telegram_chat_id` |
| Landings UTM | `/l/{slug}` + Open Graph para crawlers |
| Leads | Formulario waitlist → tabla `MarketingLead` |
| Cola | Campañas `ready` → abrir composer → publicar → **Marcar enviada** |
| Kit | `kit.md`, `ads.csv` (Ads Editor), `week.ics` (bloque de 20 min/día) |
| Link-in-bio | Público `/go` (no filtra chat_id ni tokens) |

Pantalla: **Admin → Lanzamiento / redes** (`/admin/launch`). El candidato solo ve **Invitar a un amigo** (`/invite`).

---

## 0. Origen público (obligatorio)

Los crawlers de LinkedIn/X/WhatsApp piden la URL **desde internet**, no `localhost`.

1. Elige un origen estable:
   - Tailscale: `http://100.x.y.z:8010` (o HTTPS si ya tienes Caddy).
   - Dominio: `https://jobsworld.tudominio`.
2. Ponlo en **Redes → URL pública** (queda en `data/social.json`) **o** en `.env`:

```
PUBLIC_BASE_URL=http://100.78.198.98:8010
```

3. Reinicia el API (`:8010`) si usas `.env`.
4. Comprueba:
   - Navegador: `{origen}/l/lanzamiento`
   - Crawler: `{origen}/l/lanzamiento` con User-Agent `Twitterbot` debe devolver HTML con `og:title` (el SPA fallback lo hace).

Sin origen público, UTM y previews de enlace salen rotos. El medidor *readiness* lo marca en rojo.

---

## 1. LinkedIn (orgánico, día 1)

**Page de empresa**

1. linkedin.com → Pages → Create (Company). Nombre legal coherente con `docs/LEGAL-ES.md`.
2. Logo 300×300, cover 1128×191, about 2 párrafos (cópialos del kit.md).
3. Pega la URL `https://www.linkedin.com/company/…` en Redes.

**Publicar**

LinkedIn **Share Offsite** solo pasa la URL. Flujo real:

1. Campañas → copiar texto.
2. Abrir composer LinkedIn (abre el diálogo de share).
3. Pegar el copy **en el cuerpo del post** (el share no lo rellena).
4. Publicar → Marcar enviada.

**Ads (opcional, 50–100 € de validación)**

1. Campaign Manager → cuenta asociada a la Page.
2. Objetivo: Tráfico o Leads (form nativo o a `{origen}/l/ofertas-fantasma`).
3. Importa `ads.csv` en Ads Editor **como borrador**. Revisa headlines (40 c) y Primary text (125 c). No dispares sin presupuesto diario capado (p. ej. 8 €/día, 5 días, España, 25–45, empleo/IT).
4. Pixel: Meta no es obligatorio el día 1. Si lo montas, evento `Lead` en `/l/*` tras el formulario. El backend ya registra `landing_view` y leads.

**App Review (solo si más adelante quieres API)**

- Crear app en developers.linkedin.com, producto Share.
- No bloquees el lanzamiento esperando esto.

---

## 2. X / Twitter

1. Cuenta + handle en Redes (sin `@`).
2. Composer Intent rellena texto + URL. Publica y marca enviada.
3. Card: `twitter:card=summary` + `og:image` = `{origen}/icon-512.png`. Valida en https://cards-dev.x.com/validator (o el debugger vigente).
4. Ads: Ads Manager → tráfico a `/l/remoto-espana`. CSV sirve como copy; las columnas no son el formato nativo de X Ads, pégalas a mano.

---

## 3. Telegram (el único envío automático)

1.  [@BotFather](https://t.me/BotFather) → `/newbot` → copia el token.
2. `.env`:

```
TELEGRAM_BOT_TOKEN=123456:AAE...
```

3. Crea un canal (o usa un grupo). Añade el bot como admin.
4. Obtén `chat_id`:
   - Canal público: `@nombrecanal` a veces basta.
   - Canal privado / grupo: escribe al bot, llama `https://api.telegram.org/bot{TOKEN}/getUpdates` y copia `chat.id` (canales: `-100…`).
5. Pega `telegram_chat_id` y `telegram_channel` en Redes.
6. En Campañas, canal `telegram` → **Enviar por bot**. Si falla, el JSON de error sale en pantalla (token inválido, bot no admin, chat_id mal).

Composer `t.me/share` es el fallback sin token.

---

## 4. WhatsApp, Instagram, Facebook, Threads

**WhatsApp Business**

- URL `https://wa.me/34XXXXXXXXX` o enlace a catálogo. El intent `wa.me/?text=` abre el share con copy listo (estados, grupos de empleo, listas de difusión). No hay API Cloud el día 1 sin Meta Business verificado.

**Instagram**

- Handle en Redes. Stories: pega `/go` o el QR de cada landing. Feed: copia el texto LinkedIn (más corto) a mano. Graph API de IG requiere Facebook Login + Page vinculada + review.

**Facebook Page**

- Crea Page → URL en Redes. Sharer solo lleva URL; pega el copy en la Page. Ads: mismo CSV + Campaign Manager.

**Threads**

- Intent `threads.net/intent/post`. Cuenta Meta.

---

## 5. Reddit y email

- `reddit_sub` (p. ej. `spain`, `empleos`, `cscareerquestionsEU`). Lee reglas: muchos subs prohíben autopromo. Título = hook; URL = landing UTM `utm_source=reddit`.
- Email: mailto con asunto/cuerpo. Para lista propia usa el export de leads del admin (no hay ESP integrado a propósito).

---

## 6. Landings y Open Graph

Rutas públicas:

- `/l/remoto-espana`
- `/l/valencia`
- `/l/ofertas-fantasma`
- `/l/cv-ia`
- `/l/lanzamiento`
- `/go` (bio)

UTM automáticos al compartir desde la cola: `utm_source={canal}&utm_medium=social&utm_campaign={campaña}`.

**Debuggers** (pega la URL pública, no localhost):

- LinkedIn Post Inspector
- Facebook Sharing Debugger
- X Card Validator

Si el preview no actualiza: scrap de nuevo; el HTML OG se sirve solo a User-Agents de crawler. Navegador humano ve el SPA React.

Imagen OG: `{origen}/icon-512.png`. Sustituye el PNG (mín. 200×200; LinkedIn prefiere 1200×627 si más adelante añades `og:image` específico).

Los QR de cada landing se generan vía `api.qrserver.com` (hace falta red). Si el lab no sale a internet, abre la URL en el móvil o genera el QR con cualquier app leyendo la misma URL UTM.

---

## 7. Anuncios de pago (semana 1, techo 100 €)

1. Descarga `ads.csv` desde Kit.
2. Meta Ads Editor o Google Ads Editor → importar como **borrador**.
3. Ajusta geo (España), idioma, exclusión de remarketing innecesario, URL final con UTM `utm_medium=paid`.
4. Conversiones: waitlist (`POST /api/marketing/leads`) + registros. No hay pixel automático; si usas GA4, mide `{origen}/l/*` y `/login`.
5. Mata la campaña si CPL waitlist > 8 € o CTR < 0,6 % a 48 h.

JobsWorld **no** pulsa «publicar anuncio» por ti: eso requiere OAuth de cada red y presupuesto en su consola.

---

## 8. Calendario y cola

- **Generar semana**: usa el motor de campañas (Ollama del lab si responde). Deja posts `ready`.
- **semana.ics**: un VEVENT/día a las 07:30 UTC (~09:30 Madrid en verano). Importa en Outlook/Google.
- Tras publicar en la red, **Marcar enviada**. El readiness exige al menos un `sent`.

---

## 9. Seguridad

- `data/social.json` puede contener `telegram_chat_id`. No lo subas a un repo público.
- `/go` y `/api/public/bio` **no** exponen tokens ni chat_id.
- Descargas `kit.md` / `ads.csv` / `week.ics` van autenticadas (`access_token` en query). No las enlaces en posts.

---

## 10. Checklist día 0

1. `PUBLIC_BASE_URL` o campo URL pública.
2. Handles LinkedIn + X + Telegram.
3. Token bot si vas a enviar al canal.
4. Probar `/l/lanzamiento` en el Post Inspector.
5. Generar semana → publicar 1 post LinkedIn + 1 Telegram → marcar enviadas.
6. Poner `/go` en la bio de Instagram.

Si un canal no está listo, déjalo vacío: el composer del resto sigue funcionando.
