feat: centralizar ADN y estilo de marca en Zona de Marca y simplificar panel de creatividades a operativa ads
This commit is contained in:
@@ -70,6 +70,27 @@ export type BrandPersona = {
|
||||
channels?: string;
|
||||
};
|
||||
|
||||
export type CreativeB2BPersona = {
|
||||
name: string;
|
||||
role: string;
|
||||
goal: string;
|
||||
pain_point: string;
|
||||
buying_trigger: string;
|
||||
};
|
||||
|
||||
export type CreativeB2CPersona = {
|
||||
name: string;
|
||||
age_range: string;
|
||||
situation: string;
|
||||
pain_point: string;
|
||||
goal: string;
|
||||
};
|
||||
|
||||
export type CreativeObjection = {
|
||||
objection: string;
|
||||
rebuttal: string;
|
||||
};
|
||||
|
||||
export type Brandbook = {
|
||||
version: 2;
|
||||
updated_at?: string;
|
||||
@@ -85,6 +106,11 @@ export type Brandbook = {
|
||||
vision: string;
|
||||
values: string[];
|
||||
vertical: string;
|
||||
b2b_offering?: string;
|
||||
b2c_offering?: string;
|
||||
usp_differentiators?: string;
|
||||
current_priorities?: string;
|
||||
website?: string;
|
||||
/** Voz */
|
||||
tone: string;
|
||||
personality: string[];
|
||||
@@ -96,6 +122,10 @@ export type Brandbook = {
|
||||
example_good: string[];
|
||||
example_bad: string[];
|
||||
slogan_variants: string[];
|
||||
copy_structure_rules?: string;
|
||||
english_terms_policy?: string;
|
||||
power_words?: string[];
|
||||
allowed_ctas?: string[];
|
||||
/** Visual kit */
|
||||
colors: ColorToken[];
|
||||
fonts_kit: FontToken[];
|
||||
@@ -112,10 +142,18 @@ export type Brandbook = {
|
||||
icon_style: string;
|
||||
imagery_do: string[];
|
||||
imagery_dont: string[];
|
||||
surface_rules?: string;
|
||||
image_text_rules?: string;
|
||||
typography_headline?: string;
|
||||
typography_body?: string;
|
||||
kit_assets: BrandAsset[];
|
||||
/** Audiencia */
|
||||
icp: string;
|
||||
personas: BrandPersona[];
|
||||
b2b_personas?: CreativeB2BPersona[];
|
||||
b2c_personas?: CreativeB2CPersona[];
|
||||
customer_frustrations?: string;
|
||||
desired_transformation?: string;
|
||||
geo: string;
|
||||
languages: string[];
|
||||
jobs_to_be_done: string[];
|
||||
@@ -131,6 +169,7 @@ export type Brandbook = {
|
||||
competitive_alternatives: string[];
|
||||
guarantee: string;
|
||||
pricing_notes: string;
|
||||
price_and_offer_framing?: string;
|
||||
/** Pilares */
|
||||
pillars_rrss: string[];
|
||||
series_recurrentes: string[];
|
||||
@@ -169,6 +208,9 @@ export type Brandbook = {
|
||||
ads_formats: string[];
|
||||
landing_notes: string;
|
||||
retargeting_angles: string[];
|
||||
objections?: CreativeObjection[];
|
||||
winning_hooks?: string[];
|
||||
preferred_angles?: string[];
|
||||
/** B2B */
|
||||
linkedin_themes: string[];
|
||||
linkedin_formats: string[];
|
||||
@@ -189,6 +231,9 @@ export type Brandbook = {
|
||||
legal_notes: string;
|
||||
sector_rules: string;
|
||||
image_rights: string;
|
||||
emoji_policy?: string;
|
||||
testimonials_policy?: string;
|
||||
competitors_never_mention?: string[];
|
||||
/** Fuentes */
|
||||
source_excerpts: Array<{
|
||||
id: string;
|
||||
@@ -404,6 +449,30 @@ export function emptyBrandbook(label = ''): Brandbook {
|
||||
image_rights: '',
|
||||
source_excerpts: [],
|
||||
freeform_notes: '',
|
||||
b2b_offering: '',
|
||||
b2c_offering: '',
|
||||
usp_differentiators: '',
|
||||
current_priorities: '',
|
||||
website: '',
|
||||
copy_structure_rules: '',
|
||||
english_terms_policy: '',
|
||||
power_words: [],
|
||||
allowed_ctas: [],
|
||||
surface_rules: '',
|
||||
image_text_rules: '',
|
||||
typography_headline: '',
|
||||
typography_body: '',
|
||||
b2b_personas: [],
|
||||
b2c_personas: [],
|
||||
customer_frustrations: '',
|
||||
desired_transformation: '',
|
||||
price_and_offer_framing: '',
|
||||
objections: [],
|
||||
winning_hooks: [],
|
||||
preferred_angles: [],
|
||||
emoji_policy: '',
|
||||
testimonials_policy: '',
|
||||
competitors_never_mention: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -582,6 +651,80 @@ export function seedBrandbook(slug: string, label: string): Brandbook {
|
||||
],
|
||||
value_proposition:
|
||||
'Aprendes inglés usable desde la primera semana, con camino claro a certificado.',
|
||||
b2b_offering:
|
||||
'Programas de inglés profesional para equipos. Diferencia frente a apps conversacionales tipo Twenix: profesor fijo, sesiones de 60 minutos, programas por sector (Inglés Legal, IT, Financiero, Comercial Internacional), modalidad híbrida. Es Entidad Organizadora de FUNDAE (gestiona la bonificación directamente, no a través de un partner).',
|
||||
b2c_offering:
|
||||
'Cursos de inglés para adultos, preparación de exámenes oficiales (Cambridge, Aptis, IELTS), intensivos, clases 1to1 y plataforma online.',
|
||||
usp_differentiators:
|
||||
'Profesor fijo asignado + sesiones completas de 60 min (progreso estructural frente a conversación suelta de 15-20 min en apps). Gestión integral FUNDAE como Entidad Organizadora oficial. Especialización real por vertical profesional.',
|
||||
current_priorities:
|
||||
'B2C: captación de matrículas de adultos y preparación de certificados oficiales (Cambridge / Aptis). B2B: captación de empresas que quieren aprovechar su crédito anual FUNDAE con programas in-company u online estructurados.',
|
||||
price_and_offer_framing:
|
||||
'En B2B destacar el coste bonificado vía FUNDAE (coste cero o casi cero para la empresa, expresado en coste neto o gestión bonificada). En B2C destacar el valor del programa estructurado con profesor fijo, sin recurrir nunca a descuentos agresivos ni cuentas atrás.',
|
||||
website: 'blueparrotschool.com',
|
||||
copy_structure_rules:
|
||||
'Frases cortas. Un dato concreto vale más que un adjetivo. En primary_text: 2-4 frases, máx. 300 caracteres; la frase 1 amplía el hook, frases 2-3 dan un beneficio o dato concreto, frase final cierra con el CTA sin enlaces ni hashtags.',
|
||||
english_terms_policy:
|
||||
'Inglés en el copy: solo nombres propios de exámenes (Cambridge, Aptis, IELTS) o términos sin traducción natural (in-company). Nada de "boost", "unlock", "level up".',
|
||||
power_words: [
|
||||
'Profesor fijo',
|
||||
'60 minutos',
|
||||
'Entidad Organizadora FUNDAE',
|
||||
'Inglés de tu sector',
|
||||
'Programa estructurado',
|
||||
'Madrid y Málaga + Online',
|
||||
],
|
||||
allowed_ctas: [
|
||||
'Más información',
|
||||
'Solicitar presupuesto',
|
||||
'Reservar',
|
||||
'Contactar',
|
||||
'Registrarte',
|
||||
],
|
||||
b2b_personas: [
|
||||
{
|
||||
name: 'Marta (RRHH / Formación)',
|
||||
role: 'Responsable de RRHH o Desarrollo de Talento',
|
||||
goal: 'Quiere un proveedor llave en mano que no le dé trabajo administrativo.',
|
||||
pain_point:
|
||||
'Proveedores que obligan a RRHH a gestionar papeleo FUNDAE, perseguir asistencias o lidiar con quejas por cambios constantes de profesor.',
|
||||
buying_trigger:
|
||||
'Gestión FUNDAE 100% resuelta por Blue Parrot, informes periódicos de asistencia y progreso, y un único interlocutor.',
|
||||
},
|
||||
{
|
||||
name: 'Carlos (Socio / Director de Despacho o Consultora)',
|
||||
role: 'Director General o Socio en firma legal, financiera o consultoría',
|
||||
goal: 'Que su equipo hable con clientes internacionales con solvencia y sin hacer el ridículo.',
|
||||
pain_point:
|
||||
'Su equipo sabe gramática pero se bloquea al negociar, redactar contratos o defender propuestas en inglés técnico.',
|
||||
buying_trigger:
|
||||
'Compra rigor y especialización sectorial (Inglés Legal, Financiero, IT), no "clases de inglés general".',
|
||||
},
|
||||
{
|
||||
name: 'Lucía (Directora Comercial / Internacional)',
|
||||
role: 'Directora Comercial o de Expansión Internacional',
|
||||
goal: 'Resultados medibles en poco tiempo para presentaciones, negociación y llamadas internacionales.',
|
||||
pain_point:
|
||||
'Las apps conversacionales entretienen pero el equipo sigue sin cerrar reuniones complejas en inglés.',
|
||||
buying_trigger:
|
||||
'Sesiones de 60 minutos enfocadas en casos reales de su puesto de trabajo.',
|
||||
},
|
||||
],
|
||||
b2c_personas: [
|
||||
{
|
||||
name: 'Adulto Profesional / Opositor (25-45 años)',
|
||||
age_range: '25-45 años',
|
||||
situation:
|
||||
'Trabaja o busca salto laboral / necesita certificar nivel oficial (Cambridge B2/C1, Aptis, IELTS).',
|
||||
pain_point:
|
||||
'Ha fracasado o se ha estancado con apps y cursos grabados; siente que pierde el tiempo sin un profesor que le corrija y le marque ritmo.',
|
||||
goal: 'Avanzar de nivel de forma real o aprobar su examen oficial con horario compatible con su jornada.',
|
||||
},
|
||||
],
|
||||
customer_frustrations:
|
||||
'Estancamiento en el "nivel intermedio eterno" por usar apps de 15 minutos con profesores distintos cada día que solo dan charla superficial sin estructura ni seguimiento.',
|
||||
desired_transformation:
|
||||
'Pasar de evitar hablar en inglés o depender de traductores a desenvolverse con seguridad en reuniones de trabajo o aprobar su certificación oficial a la primera.',
|
||||
ads_usps: [
|
||||
'Metodología práctica',
|
||||
'Profes preparados',
|
||||
@@ -593,6 +736,58 @@ export function seedBrandbook(slug: string, label: string): Brandbook {
|
||||
'Ya probé y no aprendí',
|
||||
'Es caro',
|
||||
],
|
||||
objections: [
|
||||
{
|
||||
objection: 'Ya usamos una app',
|
||||
rebuttal:
|
||||
'La app mantiene, no avanza. Sin profesor fijo ni sesiones de 60 min no se sale del nivel intermedio.',
|
||||
},
|
||||
{
|
||||
objection: 'Es caro',
|
||||
rebuttal:
|
||||
'Bonificación FUNDAE gestionada directamente por nosotros; coste mínimo por empleado y mes.',
|
||||
},
|
||||
{
|
||||
objection: 'No tenemos tiempo',
|
||||
rebuttal:
|
||||
'Sesiones in-company u online integradas dentro del horario laboral.',
|
||||
},
|
||||
],
|
||||
winning_hooks: [
|
||||
'Tu equipo no necesita más inglés. Necesita el inglés de su trabajo.',
|
||||
'FUNDAE lo paga. Nosotros lo gestionamos.',
|
||||
'Un profesor. Sesenta minutos. Cada semana. Así se avanza.',
|
||||
'El inglés legal no se aprende en una app.',
|
||||
],
|
||||
preferred_angles: [
|
||||
'objeción tiempo',
|
||||
'coste FUNDAE',
|
||||
'contraste app vs programa real',
|
||||
'especialización por sector (Legal / IT / Finanzas)',
|
||||
'cero carga para RRHH',
|
||||
'certificación oficial (Cambridge / Aptis)',
|
||||
],
|
||||
claims_forbidden: [
|
||||
'Prometer niveles o plazos cerrados ("B2 en 3 meses").',
|
||||
'Comparar nombrando explícitamente a la competencia (ni Twenix ni ninguna).',
|
||||
'Descuentos agresivos, cuentas atrás, "última oportunidad".',
|
||||
'Fotografía de stock genérica de "gente feliz con portátil" con aspecto de banco de imágenes.',
|
||||
'Deformar el logo, recolorearlo o recrearlo (se coloca siempre el archivo oficial en plantilla).',
|
||||
'Empezar un hook por "¿Sabías que", "Descubre" o "Imagina".',
|
||||
],
|
||||
competitors_never_mention: ['Twenix', 'Preply', 'Italki', 'Open English', "What's Up!"],
|
||||
emoji_policy:
|
||||
'Prohibidos los emojis en creatividades de imagen. En copy (primary_text), como mucho uno al inicio y solo en B2C (nunca en B2B).',
|
||||
testimonials_policy:
|
||||
'Prohibidos testimonios inventados o con nombre y cargo de personas que no existen. Si no hay un caso real aprobado, no se usa testimonio.',
|
||||
surface_rules:
|
||||
'Azul (#2A4D9C) y blanco (#FFFFFF) como base. Amarillo (#FBC02D) solo para resaltar una palabra, un dato o el CTA. Negro (#000000) reservado a mensajes de formalidad o urgencia (FUNDAE que caduca, manifiesto). Ningún otro color.',
|
||||
typography_headline: 'Poppins Extrabold (siempre en titulares / hook). Nunca otra fuente.',
|
||||
typography_body: 'Poppins Regular (en cuerpo y línea de apoyo / support).',
|
||||
image_text_rules:
|
||||
'Máximo 2 niveles en imagen (titular hook + línea de apoyo support). El titular no supera 8 palabras. Margen seguro mínimo del 8% en todos los lados; nunca texto en el 15% superior ni inferior.',
|
||||
photography_style:
|
||||
'Fotografía real de aula, oficina o reunión con luz natural; personas adultas de 25-50 años en contexto de trabajo; sin poses de catálogo. Si es ilustración o composición gráfica, geometría limpia, mucho aire y una sola idea.',
|
||||
ads_funnel: ['Awareness Reel', 'Consideración carrusel', 'Conversión test'],
|
||||
linkedin_themes: [
|
||||
'Inglés profesional',
|
||||
@@ -878,6 +1073,51 @@ export function parseBrandbook(raw: unknown): Brandbook | null {
|
||||
source_excerpts: Array.isArray(partial.source_excerpts)
|
||||
? partial.source_excerpts
|
||||
: [],
|
||||
b2b_offering: String(partial.b2b_offering || ''),
|
||||
b2c_offering: String(partial.b2c_offering || ''),
|
||||
usp_differentiators: String(partial.usp_differentiators || ''),
|
||||
current_priorities: String(partial.current_priorities || ''),
|
||||
website: String(partial.website || ''),
|
||||
copy_structure_rules: String(partial.copy_structure_rules || ''),
|
||||
english_terms_policy: String(partial.english_terms_policy || ''),
|
||||
power_words: arr(partial.power_words),
|
||||
allowed_ctas: arr(partial.allowed_ctas),
|
||||
surface_rules: String(partial.surface_rules || ''),
|
||||
image_text_rules: String(partial.image_text_rules || ''),
|
||||
typography_headline: String(partial.typography_headline || ''),
|
||||
typography_body: String(partial.typography_body || ''),
|
||||
b2b_personas: Array.isArray(partial.b2b_personas)
|
||||
? partial.b2b_personas.map((p: any) => ({
|
||||
name: String(p.name || ''),
|
||||
role: String(p.role || ''),
|
||||
goal: String(p.goal || ''),
|
||||
pain_point: String(p.pain_point || ''),
|
||||
buying_trigger: String(p.buying_trigger || ''),
|
||||
}))
|
||||
: [],
|
||||
b2c_personas: Array.isArray(partial.b2c_personas)
|
||||
? partial.b2c_personas.map((p: any) => ({
|
||||
name: String(p.name || ''),
|
||||
age_range: String(p.age_range || ''),
|
||||
situation: String(p.situation || ''),
|
||||
pain_point: String(p.pain_point || ''),
|
||||
goal: String(p.goal || ''),
|
||||
}))
|
||||
: [],
|
||||
customer_frustrations: String(partial.customer_frustrations || ''),
|
||||
desired_transformation: String(partial.desired_transformation || ''),
|
||||
price_and_offer_framing: String(partial.price_and_offer_framing || ''),
|
||||
objections: Array.isArray(partial.objections)
|
||||
? partial.objections.map((o: any) => ({
|
||||
objection: String(o.objection || ''),
|
||||
rebuttal: String(o.rebuttal || ''),
|
||||
}))
|
||||
: [],
|
||||
winning_hooks: arr(partial.winning_hooks),
|
||||
preferred_angles: arr(partial.preferred_angles),
|
||||
emoji_policy: String(partial.emoji_policy || ''),
|
||||
testimonials_policy: String(partial.testimonials_policy || ''),
|
||||
competitors_never_mention: arr(partial.competitors_never_mention),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1046,3 +1286,356 @@ export function primaryLogo(book: Brandbook): BrandAsset | undefined {
|
||||
) || book.kit_assets.find((a) => a.kind === 'logo')
|
||||
);
|
||||
}
|
||||
|
||||
export type OperativeAdsConfig = {
|
||||
image_ai?: {
|
||||
photo_style?: string;
|
||||
rule_1_5_seconds?: string;
|
||||
forbidden_scenes?: string;
|
||||
people_count_rules?: string;
|
||||
negative_space_prompt?: string;
|
||||
};
|
||||
campaign_rules?: {
|
||||
b2c_detection_rules?: string;
|
||||
b2b_detection_rules?: string;
|
||||
fallback_audience_rule?: string;
|
||||
extra_claude_instructions?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export function compileClientSkillFromBrandbook(
|
||||
book: Brandbook,
|
||||
technicalOps?: OperativeAdsConfig,
|
||||
clientName?: string,
|
||||
slug?: string
|
||||
): string {
|
||||
const name = clientName || book.brand_name || 'Cliente';
|
||||
const cSlug = slug || name.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push(`# Skill de cliente · ${name} (slug: ${cSlug})`);
|
||||
lines.push('');
|
||||
lines.push(
|
||||
`> Esta skill define cómo habla y cómo se ve ${name} en cualquier creatividad. Se inyecta como contexto fijo a Claude en cada petición de relevo. Si algo aquí contradice un brief puntual, manda esta skill.`
|
||||
);
|
||||
lines.push('');
|
||||
|
||||
// 1. Quién es
|
||||
lines.push('## Quién es');
|
||||
lines.push('');
|
||||
const summary =
|
||||
book.elevator_pitch ||
|
||||
book.mission ||
|
||||
book.positioning ||
|
||||
`${name} — actividad y propuesta de valor.`;
|
||||
lines.push(summary);
|
||||
lines.push('');
|
||||
if (book.b2b_offering) {
|
||||
lines.push(`- **B2B (empresas):** ${book.b2b_offering}`);
|
||||
}
|
||||
if (book.b2c_offering) {
|
||||
lines.push(`- **B2C (particulares):** ${book.b2c_offering}`);
|
||||
}
|
||||
const usps =
|
||||
book.usp_differentiators || book.differentiators?.join(' · ') || '';
|
||||
if (usps) {
|
||||
lines.push(`- **Diferenciación clave:** ${usps}`);
|
||||
}
|
||||
if (book.current_priorities) {
|
||||
lines.push(
|
||||
`- **Prioridades actuales y foco comercial:** ${book.current_priorities}`
|
||||
);
|
||||
}
|
||||
const priceFraming =
|
||||
book.price_and_offer_framing || book.pricing_notes || '';
|
||||
if (priceFraming) {
|
||||
lines.push(`- **Enfoque de precio / oferta:** ${priceFraming}`);
|
||||
}
|
||||
if (book.website) {
|
||||
lines.push('');
|
||||
lines.push(`Web: ${book.website}`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// 2. A quién le hablamos
|
||||
lines.push('## A quién le hablamos');
|
||||
lines.push('');
|
||||
if (book.b2b_personas && book.b2b_personas.length > 0) {
|
||||
lines.push('**B2B**');
|
||||
for (const p of book.b2b_personas) {
|
||||
const details = [p.role, p.goal, p.pain_point, p.buying_trigger]
|
||||
.filter(Boolean)
|
||||
.join('. ');
|
||||
lines.push(`- *${p.name}* — ${details}`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
if (book.b2c_personas && book.b2c_personas.length > 0) {
|
||||
lines.push('**B2C**');
|
||||
for (const p of book.b2c_personas) {
|
||||
const details = [p.age_range, p.situation, p.pain_point, p.goal]
|
||||
.filter(Boolean)
|
||||
.join('. ');
|
||||
lines.push(`- *${p.name}* — ${details}`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
if (
|
||||
(!book.b2b_personas || book.b2b_personas.length === 0) &&
|
||||
(!book.b2c_personas || book.b2c_personas.length === 0) &&
|
||||
book.personas &&
|
||||
book.personas.length > 0
|
||||
) {
|
||||
for (const p of book.personas) {
|
||||
const details = [p.description, p.pains, p.goals, p.channels]
|
||||
.filter(Boolean)
|
||||
.join('. ');
|
||||
lines.push(`- *${p.name}* — ${details}`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
const frust =
|
||||
book.customer_frustrations ||
|
||||
(book.barriers?.length ? book.barriers.join('; ') : '');
|
||||
if (frust) {
|
||||
lines.push(`- **Frustración principal previa:** ${frust}`);
|
||||
}
|
||||
const transf = book.desired_transformation || book.brand_promise || '';
|
||||
if (transf) {
|
||||
lines.push(`- **Transformación que buscan:** ${transf}`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// 3. Cómo habla
|
||||
lines.push('## Cómo habla');
|
||||
lines.push('');
|
||||
if (book.tone) lines.push(`- **Tono:** ${book.tone}`);
|
||||
const posture =
|
||||
book.positioning ||
|
||||
(book.personality?.length ? book.personality.join(', ') : '');
|
||||
if (posture) lines.push(`- **Postura:** ${posture}`);
|
||||
const langPolicy =
|
||||
book.languages && book.languages.length > 0
|
||||
? book.languages.includes('es')
|
||||
? 'Español de España, tratamiento de tú.'
|
||||
: book.languages.join(', ')
|
||||
: 'Español de España, tratamiento de tú.';
|
||||
lines.push(`- **Idioma y tratamiento:** ${langPolicy}`);
|
||||
const copyRules =
|
||||
book.copy_structure_rules ||
|
||||
(book.voice_do?.length
|
||||
? book.voice_do.join('; ')
|
||||
: 'Frases cortas. Un dato concreto vale más que un adjetivo.');
|
||||
lines.push(`- **Estructura y estilo:** ${copyRules}`);
|
||||
const englishPolicy =
|
||||
book.english_terms_policy ||
|
||||
(book.vocabulary_avoid?.length
|
||||
? `Evitar términos y jerga en inglés sin traducción: ${book.vocabulary_avoid.join(', ')}`
|
||||
: '');
|
||||
if (englishPolicy) {
|
||||
lines.push(`- **Idiomas / anglicismos en el copy:** ${englishPolicy}`);
|
||||
}
|
||||
const powers =
|
||||
book.power_words && book.power_words.length > 0
|
||||
? book.power_words
|
||||
: book.vocabulary_prefer;
|
||||
if (powers && powers.length > 0) {
|
||||
lines.push(`- **Conceptos fuerza:** ${powers.join(' · ')}`);
|
||||
}
|
||||
const ctas =
|
||||
book.allowed_ctas && book.allowed_ctas.length > 0
|
||||
? book.allowed_ctas
|
||||
: book.ads_ctas;
|
||||
if (ctas && ctas.length > 0) {
|
||||
lines.push(`- **CTAs permitidos:** ${ctas.join(', ')}`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// 4. Argumentos y objeciones
|
||||
const winArgs = book.ads_usps?.length
|
||||
? book.ads_usps
|
||||
: book.proof_points?.length
|
||||
? book.proof_points
|
||||
: book.differentiators;
|
||||
if (winArgs && winArgs.length > 0) {
|
||||
lines.push('### Argumentos que funcionan');
|
||||
winArgs.forEach((arg, idx) => {
|
||||
lines.push(`${idx + 1}. ${arg}`);
|
||||
});
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
if (book.objections && book.objections.length > 0) {
|
||||
lines.push('### Objeciones a desactivar');
|
||||
for (const obj of book.objections) {
|
||||
lines.push(`- "${obj.objection}" → ${obj.rebuttal}`);
|
||||
}
|
||||
lines.push('');
|
||||
} else if (book.ads_objections && book.ads_objections.length > 0) {
|
||||
lines.push('### Objeciones a desactivar');
|
||||
for (const obj of book.ads_objections) {
|
||||
lines.push(`- "${obj}"`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
if (book.proof_points && book.proof_points.length > 0) {
|
||||
lines.push('### Pruebas y datos reales verificados');
|
||||
for (const pt of book.proof_points) {
|
||||
lines.push(`- ${pt}`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
const angles =
|
||||
book.preferred_angles && book.preferred_angles.length > 0
|
||||
? book.preferred_angles
|
||||
: book.ads_angles;
|
||||
if (angles && angles.length > 0) {
|
||||
lines.push(
|
||||
`### Ángulos recomendados para rotar\n- ${angles.join(' · ')}\n`
|
||||
);
|
||||
}
|
||||
|
||||
// 5. Prohibido
|
||||
lines.push('## Prohibido');
|
||||
const forbidden =
|
||||
book.claims_forbidden && book.claims_forbidden.length > 0
|
||||
? book.claims_forbidden
|
||||
: [
|
||||
'Promesas irreales o plazos garantizados sin base.',
|
||||
'Fotografía genérica con aspecto artificial.',
|
||||
'Deformar o recrear el logo mediante IA.',
|
||||
];
|
||||
for (const item of forbidden) {
|
||||
lines.push(`- ${item}`);
|
||||
}
|
||||
if (
|
||||
book.competitors_never_mention &&
|
||||
book.competitors_never_mention.length > 0
|
||||
) {
|
||||
lines.push(
|
||||
`- Prohibido mencionar a competidores (${book.competitors_never_mention.join(', ')}).`
|
||||
);
|
||||
}
|
||||
if (book.emoji_policy) {
|
||||
lines.push(`- **Emojis:** ${book.emoji_policy}`);
|
||||
}
|
||||
if (book.testimonials_policy) {
|
||||
lines.push(`- **Testimonios:** ${book.testimonials_policy}`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// 6. Identidad visual
|
||||
lines.push('## Identidad visual');
|
||||
lines.push('');
|
||||
if (book.colors && book.colors.length > 0) {
|
||||
const paletteStr = book.colors
|
||||
.map((c) => `${c.name} \`${c.hex}\` (${c.usage || c.role})`)
|
||||
.join(' · ');
|
||||
lines.push(`- **Paleta exacta y única:** ${paletteStr}`);
|
||||
}
|
||||
if (book.surface_rules) {
|
||||
lines.push(`- **Uso de superficies:** ${book.surface_rules}`);
|
||||
}
|
||||
const headFont =
|
||||
book.typography_headline ||
|
||||
book.fonts_kit?.find(
|
||||
(f) => f.role === 'headline' || f.role === 'display'
|
||||
)?.family ||
|
||||
'N/A';
|
||||
const bodyFont =
|
||||
book.typography_body ||
|
||||
book.fonts_kit?.find((f) => f.role === 'body')?.family ||
|
||||
'N/A';
|
||||
if (headFont !== 'N/A' || bodyFont !== 'N/A') {
|
||||
lines.push(
|
||||
`- **Tipografía:** Titulares: ${headFont}. Cuerpo/Apoyo: ${bodyFont}.`
|
||||
);
|
||||
}
|
||||
const logoText =
|
||||
book.logo_usage ||
|
||||
'Logo oficial de marca con área de protección respetada en esquina; nunca centrado ni dominando.';
|
||||
lines.push(`- **Logo:** ${logoText}`);
|
||||
|
||||
const photoStyle =
|
||||
technicalOps?.image_ai?.photo_style ||
|
||||
book.photography_style ||
|
||||
'Fotografía realista con luz natural, personas reales en contexto del servicio, sin poses forzadas.';
|
||||
lines.push(`- **Estilo de imagen:** ${photoStyle}`);
|
||||
|
||||
const rule15 =
|
||||
technicalOps?.image_ai?.rule_1_5_seconds ||
|
||||
'La escena debe mostrar claramente el producto o servicio en menos de 1,5 segundos sin necesidad de leer el texto.';
|
||||
lines.push(`- **Regla de lectura en 1,5 s:** ${rule15}`);
|
||||
|
||||
const forbiddenScenes =
|
||||
technicalOps?.image_ai?.forbidden_scenes ||
|
||||
(book.imagery_dont?.length
|
||||
? book.imagery_dont.join('; ')
|
||||
: 'Escenas ambiguas que puedan confundirse con otro sector o stock genérico.');
|
||||
lines.push(`- **Escenas a evitar en imagen:** ${forbiddenScenes}`);
|
||||
|
||||
const peopleCount =
|
||||
technicalOps?.image_ai?.people_count_rules ||
|
||||
'1 persona si el mensaje es individual; 2 personas si muestra interacción profesional.';
|
||||
lines.push(`- **Personas en escena:** ${peopleCount}`);
|
||||
|
||||
const negSpace =
|
||||
technicalOps?.image_ai?.negative_space_prompt ||
|
||||
'the upper third of the frame is empty wall or sky. no text, no logos, no watermarks, photorealistic, vertical 4:5 composition with clear negative space for a headline.';
|
||||
lines.push(`- **Espacio negativo (image_prompt):** ${negSpace}`);
|
||||
|
||||
const imgText =
|
||||
book.image_text_rules ||
|
||||
'Máximo 2 niveles (titular ≤ 8 palabras + apoyo ≤ 12 palabras). Margen mínimo del 8% en todos los lados.';
|
||||
lines.push(`- **Texto en imagen:** ${imgText}`);
|
||||
lines.push('');
|
||||
|
||||
// 7. Audiencia por campaña
|
||||
lines.push('## Audiencia por campaña');
|
||||
lines.push('');
|
||||
lines.push(
|
||||
'El brief trae `audience`. Si no viene, se deduce del nombre de campaña:'
|
||||
);
|
||||
const b2cDet =
|
||||
technicalOps?.campaign_rules?.b2c_detection_rules ||
|
||||
'Campañas B2C: dolor personal, cursos individuales, examen oficial. Habla siempre de "tu".';
|
||||
lines.push(`- **B2C:** ${b2cDet}`);
|
||||
const b2bDet =
|
||||
technicalOps?.campaign_rules?.b2b_detection_rules ||
|
||||
'Campañas B2B: foco en equipos, formación para empresas, bonificación. Habla siempre de "tu equipo".';
|
||||
lines.push(`- **B2B:** ${b2bDet}`);
|
||||
const fallbackAud =
|
||||
technicalOps?.campaign_rules?.fallback_audience_rule ||
|
||||
'Si el brief no trae audience y no se puede deducir del nombre de campaña, se pregunta en notes y se genera en B2C.';
|
||||
lines.push(fallbackAud);
|
||||
lines.push('');
|
||||
|
||||
// 8. Ejemplos de hooks
|
||||
const hooks =
|
||||
book.winning_hooks && book.winning_hooks.length > 0
|
||||
? book.winning_hooks
|
||||
: book.slogan_variants;
|
||||
if (hooks && hooks.length > 0) {
|
||||
lines.push(
|
||||
'## Ejemplos de hooks que han funcionado (referencia de registro, no para copiar)'
|
||||
);
|
||||
for (const h of hooks) {
|
||||
lines.push(`- "${h}"`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
const extra =
|
||||
technicalOps?.campaign_rules?.extra_claude_instructions?.trim() ||
|
||||
book.freeform_notes?.trim();
|
||||
if (extra) {
|
||||
lines.push('## Instrucciones adicionales específicas del cliente');
|
||||
lines.push(extra);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user