### Por qué las plantillas van en código, no en prompts dinámicos
Adrià descubrió que pasarle toda la lógica de diseño a un LLM genera inconsistencia. La solución: plantillas fijas en código Python. Lo único que varía entre carruseles son las variables de contenido que se inyectan en esas plantillas (generadas en el Paso 3).
Esto garantiza que los 5 carruseles del batch mantengan exactamente la misma calidad visual y estructura narrativa, cambiando solo el concepto/historia.
### Template A: Slide 1 — "El antes" (dolor/acné)
SLIDE1_PROMPT = """
A photorealistic image of a {gender} in their early 20s, crying softly,
close-up selfie angle. Their face has visible {acne_severity} acne:
{acne_description}. The lighting is harsh bathroom fluorescent,
casting unflattering shadows. The expression conveys genuine emotional
pain and insecurity. Raw, unfiltered, no makeup. Tears visible on cheeks.
The background is a messy bathroom mirror with water spots.
Aspect ratio 9:16 vertical, phone selfie style.
Generate ONLY the image — no text overlays.
"""
### Template B: Slide 2 — "El después" (glow-up)
SLIDE2_PROMPT = """
A photorealistic image of the SAME person from the previous image —
same facial structure, same hair color ({hair_color}), same eye color
({eye_color}), same face shape ({face_shape}). But now their skin is
absolutely flawless, glowing, glass-skin effect. Confident expression,
soft smile, looking directly at the camera. Golden hour natural lighting,
warm tones. The person looks radiant, happy, and transformed.
Studio-quality portrait, 9:16 vertical.
Generate ONLY the image — no text overlays.
IMPORTANT: This must look like the same person, just with clear skin
and better lighting/mood.
"""
### Template C: Slide 3 — "Lockscreen con CTA"
SLIDE3_PROMPT = """
A smartphone lockscreen screenshot, 9:16 vertical. The lockscreen shows:
- Time display at the top: {time_display}
- A direct message notification from Instagram: "{dm_text}"
- A Snapchat streak notification showing {streak_days} day streak
- The background is a subtle gradient in {bg_color}
- The overall vibe is mysterious and intriguing — making viewers
curious about what the DM conversation contains.
Generate ONLY the lockscreen image — no real UI elements that would
be detected as fake.
"""
### Código del motor de templates
from dataclasses import dataclass
from typing import Dict
@dataclass
class CarouselVariables:
"""Variables inyectables generadas por Claude Haiku."""
gender: str
acne_severity: str
acne_description: str
hair_color: str
eye_color: str
face_shape: str
time_display: str
dm_text: str
streak_days: int
bg_color: str
hook_text: str # Para overlay manual en TikTok
class PromptTemplates:
"""Plantillas fijas. Lo único que cambia son las variables."""
SLIDE1 = SLIDE1_PROMPT # Template fijo arriba
SLIDE2 = SLIDE2_PROMPT
SLIDE3 = SLIDE3_PROMPT
@classmethod
def render_slide1(cls, vars: CarouselVariables) -> str:
return cls.SLIDE1.format(
gender=vars.gender,
acne_severity=vars.acne_severity,
acne_description=vars.acne_description,
)
@classmethod
def render_slide2(cls, vars: CarouselVariables) -> str:
return cls.SLIDE2.format(
hair_color=vars.hair_color,
eye_color=vars.eye_color,
face_shape=vars.face_shape,
)
@classmethod
def render_slide3(cls, vars: CarouselVariables) -> str:
return cls.SLIDE3.format(
time_display=vars.time_display,
dm_text=vars.dm_text,
streak_days=vars.streak_days,
bg_color=vars.bg_color,
)
> Principio clave: Las plantillas son código sagrado. Se versionan, se testean, y solo se modifican con aprobación después de un test A/B que demuestre mejor rendimiento.