- FEATURES_OVERVIEW.md: Complete summary of all system features - ANALYTICS.md: Analytics and reporting system documentation - ODOO_INTEGRATION.md: Odoo ERP integration guide - AB_TESTING.md: A/B testing system documentation - CONTENT_RECYCLING.md: Content recycling system docs - THREAD_SERIES.md: Thread series and scheduled posts - IMAGE_TEMPLATES.md: Visual template system documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
351 lines
8.1 KiB
Markdown
351 lines
8.1 KiB
Markdown
# Image Templates
|
|
|
|
Sistema de plantillas para generar imágenes dinámicas.
|
|
|
|
## Descripción
|
|
|
|
Las plantillas de imagen permiten:
|
|
- Definir diseños reutilizables en HTML/CSS
|
|
- Insertar variables dinámicas
|
|
- Generar imágenes para diferentes plataformas
|
|
- Mantener consistencia visual
|
|
|
|
## Modelo de Datos
|
|
|
|
### ImageTemplate
|
|
|
|
```python
|
|
ImageTemplate:
|
|
id: int
|
|
name: str
|
|
description: str
|
|
|
|
category: str # tip, producto, servicio, promocion, etc.
|
|
template_type: str # tip_card, product_card, quote, promo, announcement
|
|
|
|
# Plantilla
|
|
template_file: str # Ruta a archivo (opcional)
|
|
html_template: str # HTML inline
|
|
|
|
preview_url: str # URL de imagen preview
|
|
|
|
# Variables
|
|
variables: [str] # ["title", "content", "accent_color"]
|
|
|
|
# Configuración de diseño
|
|
design_config: JSON
|
|
# {
|
|
# "width": 1080,
|
|
# "height": 1080,
|
|
# "background_color": "#1a1a2e",
|
|
# "accent_color": "#d4a574",
|
|
# "font_family": "Inter"
|
|
# }
|
|
|
|
# Tamaños de salida
|
|
output_sizes: JSON
|
|
# {
|
|
# "instagram": {"width": 1080, "height": 1080},
|
|
# "x": {"width": 1200, "height": 675},
|
|
# "facebook": {"width": 1200, "height": 630}
|
|
# }
|
|
|
|
is_active: bool
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### GET /api/templates/
|
|
Lista todas las plantillas.
|
|
|
|
**Parámetros:**
|
|
- `category`: tip, producto, servicio, etc.
|
|
- `template_type`: tip_card, product_card, etc.
|
|
- `active_only` (bool, default=true)
|
|
- `limit` (int, default=50)
|
|
|
|
**Respuesta:**
|
|
```json
|
|
{
|
|
"templates": [
|
|
{
|
|
"id": 1,
|
|
"name": "Tip Card Oscuro",
|
|
"description": "Tarjeta para tips con fondo oscuro",
|
|
"category": "tip",
|
|
"template_type": "tip_card",
|
|
"variables": ["title", "content", "emoji"],
|
|
"preview_url": "/uploads/previews/tip_card_dark.png"
|
|
}
|
|
],
|
|
"count": 10
|
|
}
|
|
```
|
|
|
|
### GET /api/templates/{template_id}
|
|
Obtiene una plantilla con detalles completos.
|
|
|
|
Incluye `full_html_template` con el HTML completo.
|
|
|
|
### POST /api/templates/
|
|
Crea una nueva plantilla.
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"name": "Quote Card",
|
|
"description": "Tarjeta para frases motivacionales",
|
|
"category": "frase",
|
|
"template_type": "quote",
|
|
"html_template": "<div class='card'>...</div>",
|
|
"variables": ["quote", "author", "background_image"],
|
|
"design_config": {
|
|
"width": 1080,
|
|
"height": 1080,
|
|
"background_color": "#1a1a2e"
|
|
},
|
|
"output_sizes": {
|
|
"instagram": {"width": 1080, "height": 1080},
|
|
"x": {"width": 1200, "height": 675}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Validación:**
|
|
- Requiere `html_template` o `template_file`
|
|
|
|
### PUT /api/templates/{template_id}
|
|
Actualiza una plantilla.
|
|
|
|
### DELETE /api/templates/{template_id}
|
|
Elimina una plantilla.
|
|
|
|
### POST /api/templates/preview
|
|
Genera preview de una plantilla con variables.
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"template_id": 1,
|
|
"variables": {
|
|
"title": "Tip del día",
|
|
"content": "Automatiza tus procesos con IA",
|
|
"emoji": "💡"
|
|
},
|
|
"output_size": {"width": 1080, "height": 1080}
|
|
}
|
|
```
|
|
|
|
O con HTML directo:
|
|
```json
|
|
{
|
|
"html_template": "<div>{{title}}</div>",
|
|
"variables": {
|
|
"title": "Mi título"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Respuesta:**
|
|
```json
|
|
{
|
|
"rendered_html": "<div>Mi título</div>",
|
|
"output_size": {"width": 1080, "height": 1080},
|
|
"variables_used": ["title"]
|
|
}
|
|
```
|
|
|
|
### GET /api/templates/categories/list
|
|
Lista categorías disponibles.
|
|
|
|
### GET /api/templates/types/list
|
|
Lista tipos de plantilla disponibles.
|
|
|
|
## Estructura HTML
|
|
|
|
### Variables
|
|
Las variables se definen con doble llave: `{{variable}}`
|
|
|
|
```html
|
|
<div class="card">
|
|
<span class="emoji">{{emoji}}</span>
|
|
<h1>{{title}}</h1>
|
|
<p>{{content}}</p>
|
|
</div>
|
|
```
|
|
|
|
### Ejemplo Completo
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
width: 1080px;
|
|
height: 1080px;
|
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
font-family: 'Inter', sans-serif;
|
|
color: #ffffff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.card {
|
|
width: 900px;
|
|
padding: 60px;
|
|
background: rgba(255,255,255,0.05);
|
|
border-radius: 24px;
|
|
border: 1px solid rgba(212, 165, 116, 0.3);
|
|
}
|
|
.emoji {
|
|
font-size: 64px;
|
|
display: block;
|
|
margin-bottom: 24px;
|
|
}
|
|
h1 {
|
|
color: #d4a574;
|
|
font-size: 36px;
|
|
margin-bottom: 24px;
|
|
}
|
|
p {
|
|
font-size: 24px;
|
|
line-height: 1.6;
|
|
color: #e0e0e0;
|
|
}
|
|
.footer {
|
|
margin-top: 40px;
|
|
color: #888;
|
|
font-size: 18px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="card">
|
|
<span class="emoji">{{emoji}}</span>
|
|
<h1>{{title}}</h1>
|
|
<p>{{content}}</p>
|
|
<div class="footer">@{{username}} • Consultoría AS</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
## Categorías
|
|
|
|
| Categoría | Uso |
|
|
|-----------|-----|
|
|
| `tip` | Tips tecnológicos |
|
|
| `producto` | Fichas de producto |
|
|
| `servicio` | Promoción de servicios |
|
|
| `promocion` | Ofertas y descuentos |
|
|
| `frase` | Frases motivacionales |
|
|
| `dato` | Datos curiosos |
|
|
| `anuncio` | Anuncios generales |
|
|
|
|
## Tipos de Plantilla
|
|
|
|
| Tipo | Descripción |
|
|
|------|-------------|
|
|
| `tip_card` | Tarjeta de tip con emoji |
|
|
| `product_card` | Ficha de producto con imagen |
|
|
| `quote` | Frase con autor |
|
|
| `promo` | Promoción con precio |
|
|
| `announcement` | Anuncio destacado |
|
|
| `stats` | Estadísticas/números |
|
|
| `comparison` | Antes/después o A vs B |
|
|
|
|
## Tamaños por Plataforma
|
|
|
|
| Plataforma | Ancho | Alto | Ratio |
|
|
|------------|-------|------|-------|
|
|
| Instagram Post | 1080 | 1080 | 1:1 |
|
|
| Instagram Story | 1080 | 1920 | 9:16 |
|
|
| X (Twitter) | 1200 | 675 | 16:9 |
|
|
| Facebook | 1200 | 630 | 1.91:1 |
|
|
| LinkedIn | 1200 | 627 | 1.91:1 |
|
|
| Threads | 1080 | 1080 | 1:1 |
|
|
|
|
## Ejemplo de Uso
|
|
|
|
```python
|
|
from app.models.image_template import ImageTemplate
|
|
from app.core.database import SessionLocal
|
|
|
|
db = SessionLocal()
|
|
|
|
# Crear plantilla
|
|
template = ImageTemplate(
|
|
name="Tip Card Dark",
|
|
category="tip",
|
|
template_type="tip_card",
|
|
html_template="""
|
|
<div style="...">
|
|
<h1>{{title}}</h1>
|
|
<p>{{content}}</p>
|
|
</div>
|
|
""",
|
|
variables=["title", "content"],
|
|
design_config={
|
|
"width": 1080,
|
|
"height": 1080,
|
|
"background_color": "#1a1a2e"
|
|
}
|
|
)
|
|
db.add(template)
|
|
db.commit()
|
|
|
|
# Renderizar
|
|
html = template.html_template
|
|
html = html.replace("{{title}}", "Mi Título")
|
|
html = html.replace("{{content}}", "Mi contenido")
|
|
```
|
|
|
|
## Generación de Imágenes
|
|
|
|
Para convertir HTML a imagen se recomienda:
|
|
|
|
### Playwright (recomendado)
|
|
```python
|
|
from playwright.async_api import async_playwright
|
|
|
|
async def html_to_image(html: str, width: int, height: int) -> bytes:
|
|
async with async_playwright() as p:
|
|
browser = await p.chromium.launch()
|
|
page = await browser.new_page(viewport={"width": width, "height": height})
|
|
await page.set_content(html)
|
|
screenshot = await page.screenshot(type="png")
|
|
await browser.close()
|
|
return screenshot
|
|
```
|
|
|
|
### WeasyPrint (alternativa)
|
|
```python
|
|
from weasyprint import HTML
|
|
|
|
def html_to_pdf(html: str) -> bytes:
|
|
return HTML(string=html).write_pdf()
|
|
```
|
|
|
|
## Mejores Prácticas
|
|
|
|
1. **Fuentes web:** Usa Google Fonts o incluye fuentes inline
|
|
2. **Colores consistentes:** Define palette en design_config
|
|
3. **Responsive:** Usa unidades relativas cuando sea posible
|
|
4. **Contraste:** Asegura legibilidad texto/fondo
|
|
5. **Logo:** Incluye branding en todas las plantillas
|
|
6. **Variables descriptivas:** `{{product_name}}` mejor que `{{name}}`
|
|
7. **Fallbacks:** Define valores por defecto para variables opcionales
|
|
|
|
## Integración con Posts
|
|
|
|
```python
|
|
# Al crear un post con imagen generada
|
|
post = Post(
|
|
content="Tip del día...",
|
|
image_template_id=template.id, # Referencia a la plantilla usada
|
|
image_url="/uploads/generated/tip_123.png"
|
|
)
|
|
```
|