# Estándar de Producto Self-Service

> Fecha: 2026-04-02
> Productos validados: 2
> 1. Personal Brand (demo-accounting-2) — Ref: COKE (bp-coke)
> 2. Construction-2 (demo-construction-2) — Ref: Sur Nuevo Norte (bp-surnuevonorte)

---

## Qué es un producto self-service

Un producto que el usuario final recibe listo para usar. Entra al admin, personaliza su marca, carga su contenido, y tiene su sitio profesional funcionando.

**Sin intervención de desarrollador. Sin CD como intermediario obligatorio.**

```
USUARIO COMPRA → SITIO SE PROVISIONA → USUARIO ENTRA AL ADMIN → PERSONALIZA → SITIO ONLINE
     (1 min)         (automático)           (inmediato)          (30 min)       (listo)
```

---

## Qué debe tener un core JSON para ser self-service

El core JSON (`database/seeders/products/core/{slug}.json`) es la fuente de verdad del producto. Define TODO lo que el sitio tiene de fábrica.

### Campos obligatorios

```json
{
  "demo": "demo-accounting-2",
  "modules": ["gallery", "blog", "projects", "faqs"],
  "modules_navigation": {
    "projects": { "header": true, "footer": true },
    "blog":     { "header": true, "footer": true },
    "gallery":  { "header": true, "footer": true },
    "faqs":     { "header": false, "footer": true }
  },
  "skin": "auto",
  "fonts": {
    "primary": "Lexend",
    "secondary": "Lexend",
    "tertiary": "Open Sans"
  },
  "schema_type": "Person",
  "header": {
    "cta_button": { "active": false, "title": "", "url": "", "target": "_self" }
  },
  "tagline": "...",
  "description": "...",
  "footer": {
    "navegacion_principal": {
      "inicio": { "active": false },
      "...módulos...": { "active": true, "order": 1, "url": "/path", "title": ["ES", "EN"] }
    },
    "about_title": "...",
    "description": "...",
    "tagline": "...",
    "tagline_highlight": "...",
    "tagline_suffix": "...",
    "copyright_text": "Todos los derechos reservados.",
    "newsletter_title": "Newsletter",
    "newsletter_text": "..."
  },
  "welcome": {
    "cta_primary_label": "...",
    "cta_secondary_label": "...",
    "tab_1_label": "...",
    "tab_2_label": "...",
    "tab_3_label": "...",
    "stat_1_value": "...",
    "stat_1_label": "...",
    "stat_2_value": "...",
    "stat_2_label": "...",
    "stat_3_value": "...",
    "stat_3_label": "...",
    "gallery_heading": "...",
    "projects_heading": "..."
  },
  "about": {
    "main_title": "...",
    "main_subtitle": "...",
    "main_description": "...",
    "value_1_title": "...",
    "value_1_description": "...",
    "value_2_title": "...",
    "value_2_description": "...",
    "value_3_title": "...",
    "value_3_description": "..."
  },
  "contact": {
    "page_title": "Contacto",
    "page_subtitle": "...",
    "success_message": "...",
    "response_time": "..."
  },
  "seo": {
    "keywords": "..."
  }
}
```

### Seeds obligatorios

```
database/seeders/products/core/seeds/
├── faqs-{core}.json       ← 8-12 FAQs genéricas del producto
└── blog-{core}.json       ← 3 blog posts de ejemplo
```

(services-{core}.json solo si el producto tiene módulo services)

---

## Lo que el usuario puede editar desde /admin

### Sidebar del admin

```
── MI SITIO ──
🏷️  Mi Marca        → Nombre, tagline, descripción + logos + colores + fonts
🏠 Inicio           → CTAs, pilares/tabs, stats, headings de secciones
👤 Sobre Mí         → Título, descripción, 3 pilares/valores
📞 Contacto         → Datos de contacto + redes sociales

── MI CONTENIDO ──
📝 Blog             → Crear/editar posts
📁 Proyectos        → Portfolio
🖼️  Galería          → Fotos
❓ Preguntas        → FAQs
(+ otros módulos según producto)

── HERRAMIENTAS ──
✉️  Mensajes         → Formularios recibidos
📧 Suscriptores     → Newsletter
🖼️  Banner           → Carousel hero (si el demo lo usa)
```

### Qué edita en cada tab de "Mi Sitio"

**Mi Marca:**
- Nombre del sitio
- Tagline + descripción
- 4 logos (upload a Cloudinary)
- 6 colores (color picker → genera skin CSS)
- 3 fonts (selector Google Fonts)
- Hero image (upload)

**Inicio:**
- Labels de CTAs del hero
- 3 pilares/tabs
- 3 stats (valor + etiqueta)
- Headings de galería y proyectos

**Sobre Mí:**
- Título + subtítulo
- 2 párrafos de descripción
- 3 valores/pilares (título + descripción)

**Contacto:**
- Phone, email, address, horario
- Redes sociales (toggles + URLs)

**Campos adicionales por tipo de demo:**

Algunos demos exponen campos extra en el admin. Esto se controla con condicionales `@if(in_array($activeDemo, [...]))` en `admin/site-data/index.blade.php`.

| Campo admin | Demos que lo usan | Tab |
|-------------|------------------|-----|
| About inline (heading + texto) | construction, construction-2, restaurant, law-firm-2, architecture-2, transportation | Inicio |
| Headings secciones (servicios, proyectos, CTA) | construction, construction-2, restaurant, law-firm-2, architecture-2, transportation | Inicio |
| 3 Pilares/Tabs | accounting-2 | Inicio |
| 3 Stats (value + label) | accounting-2 | Inicio |
| 4 Counters (valor + sufijo + etiqueta) | construction, construction-2, real-estate, insurance | Empresa |
| 3 Pilares/Valores (titulo + desc) | accounting-2 | Empresa |
| Team badge + titulo | construction-2, construction, law-firm-2, insurance, accounting-1 | Empresa |
| Testimonials badge + titulo | construction-2, construction, law-firm-2, insurance, accounting-1 | Empresa |
| CTA titulo + boton (about) | todos | Empresa |
| Page badge + titulo + subtitulo (contacto) | todos | Contacto |
| Card subtitle (contacto) | todos | Contacto |
| CTA badge + titulo + subtitulo (contacto) | todos | Contacto |

---

## Proceso de provisión

### Camino A: BewPro automático (self-service)

```bash
php artisan bewpro:new email@cliente.com "Nombre" personal-brand
```

El sitio llega con:
- Demo visual completo (header, footer, CSS, page-headers)
- Navegación estratégica configurada
- Textos de welcome/about/contact con defaults del producto
- 10 FAQs genéricas + 3 blog posts
- Admin panel listo para customizar
- Sin assets (el usuario los sube desde /admin)

### Camino B: CD como reseller (personalizado)

```bash
# 1. Skin custom
php artisan bewpro:skin --from-demo=accounting-2 --primary=#E91E63 --secondary=#1A1A1A --output=skin-cliente.css

# 2. Provision con JSON completo
php artisan bewpro:provision database/seeders/project-data/provision-cliente.json

# 3. Assets
cp ~/assets-cliente/* public/cd-project/assets/
php artisan db:seed --class=AssetsSeeder --force
```

---

## Checklist para crear un nuevo producto

Para llevar cualquier core al estándar self-service:

```
CORE JSON
[ ] demo definido
[ ] modules definidos
[ ] modules_navigation con orden estrategico (inicio: false)
[ ] fonts con defaults
[ ] header.cta_button configurado
[ ] tagline con texto generico del producto
[ ] description con texto generico
[ ] footer completo (nav, taglines, newsletter text)
[ ] welcome completo (CTAs, headings de secciones, split text si aplica)
[ ] about completo (page_title, main_subtitle, descriptions, cta_title, cta_label)
[ ] contact completo (page_badge, page_title, page_subtitle, card_subtitle, cta_badge, cta_title, cta_subtitle)
[ ] seo.keywords con terminos del producto

CATALOG
[ ] Entries en catalog.json apuntan a este core (N shop slugs → 1 core)
[ ] bewpro:products {core} muestra las variantes

SEEDS
[ ] faqs-{core}.json (8-12 FAQs relevantes, 3 categorias)
[ ] blog-{core}.json (3 posts, 2 categorias)
[ ] services-{core}.json (si el producto tiene modulo services)

DEMO — TEMPLATE
[ ] Header dinamico (nav por modulos, CTA config, logo config, social config)
[ ] Footer dinamico (nav por modulos, contacto config, social, proyectos recientes)
[ ] Page-header registrado (config/page-headers.php)
[ ] Skin mapping registrado (helpers.php → get_demo_skin_mapping)
[ ] CSS con overrides de modulos (retintado sections, cards, links, pagination)
[ ] Dynamic headers para todos los modulos activos
[ ] Welcome: 0 textos hardcodeados, todos via config() con defaults del referente
[ ] About: 0 textos hardcodeados, cada seccion con su propio config key
[ ] Contact: 0 textos hardcodeados, form funcional, mapa, CTA propio

ADMIN — EDITABILIDAD
[ ] CADA texto visible en front tiene un campo en /admin/site-data
[ ] Keys de blade coinciden EXACTAMENTE con los que guarda el controller
[ ] Reglas de validacion para todos los campos nuevos
[ ] Condicionales por demo en admin (campos especificos aparecen/desaparecen)
[ ] Guardar en cada tab refleja en el front (test manual)
[ ] CTA keys separados por pagina (welcome.cta_title ≠ about.cta_title ≠ contact.cta_title)

TEST
[ ] bewpro:new --dry-run sin errores
[ ] bewpro:new con DB temporal provisiona OK
[ ] Front renderiza con defaults del core JSON
[ ] Seeds se cargan (FAQs + Blog + Services)
[ ] Comparacion visual con referente online: identico
[ ] DB local coincide con textos del referente online
```

---

## Arquitectura: cómo fluyen los datos

```
core/{slug}.json (defaults del producto)
       ↓
ProvisionNew (array_replace_recursive con datos del comando)
       ↓
buildSiteData() → SiteConfigService::setMany()
       ↓
DB tabla settings (site.* keys)
       ↓
config('site.*') → Blade views
       ↓
Frontend renderiza con datos de DB
       ↓
Admin /site-data → edita settings → cache clear → front actualizado
```

---

## Proceso de validacion de un producto

Para considerar un producto validado, se ejecuta un proceso de 5 pasos contra un proyecto referente online.

### Paso 1: Comparacion visual y textual

Abrir el proyecto referente online y comparar seccion por seccion con la vista local:
- Homepage (welcome): cada seccion, cada texto, cada CTA
- About: intro, servicios, galeria, counters, equipo, testimonios, CTA
- Contact: badge, titulo, subtitulo, formulario, card, mapa, CTA

**Criterio:** Los textos deben ser identicos. Si difieren, o la DB tiene valores viejos o el blade tiene defaults incorrectos.

### Paso 2: Verificar editabilidad desde admin

Para CADA texto visible en el front, verificar:
1. El blade usa `config('site.{key}')` (no hardcodeado)
2. El admin panel tiene un campo que guarda ese key
3. El controller procesa y guarda el campo
4. Las reglas de validacion existen

**Regla clave:** Cada pagina (welcome, about, contact) debe tener sus propios config keys. NO compartir keys entre paginas (ej: el CTA de about usa `about.cta_title`, no `contact.cta_title`).

### Paso 3: Verificar provision

```bash
# Dry-run: ver el plan sin ejecutar
php artisan bewpro:new test@test.com "Test" {core-slug} --dry-run --skip-assets

# Provision real en DB temporal
php artisan bewpro:new test@test.com "Test" {core-slug} --skip-assets --db=bp-test-{slug}
```

Verificar:
- [ ] Dry-run exitoso sin errores
- [ ] Provision real crea DB y carga datos
- [ ] Front renderiza con defaults del core JSON
- [ ] Seeds se cargan (FAQs, blog, services si aplica)
- [ ] Admin panel funciona

### Paso 4: Verificar integracion de modulos

Para cada modulo activo:
- [ ] Dynamic header incluye `page-header-{demo}` (consistencia visual)
- [ ] CSS del demo tiene overrides para el modulo (retintado, cards, etc.)
- [ ] Index y show renderizan correctamente con el tema del demo
- [ ] Datos del admin se reflejan en el front

### Paso 5: Documentar y marcar como validado

1. Completar checklist en `product-readiness/checklist-{core}.md`
2. Actualizar entrada en `catalogo-productos.md` con campos admin especificos
3. Actualizar `producto-self-service.md` si el proceso revelo patrones nuevos
4. Marcar como validado en Airtable Products

**Resultado:** producto-self-service.md + catalogo-productos.md + checklist-{core}.md = fuente de verdad del producto.

---

## Aprendizajes del proceso de validacion

### Construction-2 (2do producto validado, 2026-04-02)

Problemas encontrados y resueltos:

| Problema | Causa raiz | Solucion | Aplica a futuros |
|----------|-----------|---------|-----------------|
| Keys desalineados entre blade y admin | Vista leia `page_title`, admin guardaba `main_title` | Alinear con fallbacks | SI — verificar SIEMPRE que el key del admin coincida con el del blade |
| Textos hardcodeados en vistas | Desarrollo rapido sin dinamizar | Reemplazar por `config()` | SI — cero strings hardcodeados en vistas de producto |
| Keys compartidos entre paginas | CTA de about/welcome/contact usaban el mismo key | Separar: `about.cta_title`, `contact.cta_title`, `welcome.cta_title` | SI — cada pagina sus propios keys |
| DB con textos viejos | Edicion manual durante desarrollo que quedo desactualizada | Sync DB con referente online | SI — la DB del proyecto referente DEBE coincidir con el online |
| Campos no editables | Vista usaba config() pero admin no tenia el campo | Agregar campos al admin + controller + validacion | SI — auditar editabilidad end-to-end |
| catalog.json sin entries | Core nuevo no agregado al catalogo | Agregar/reasignar entries | SI — verificar catalog mapping en provision |

### Patron de config keys por pagina

Cada pagina tiene su propio namespace de config keys. NO mezclar entre paginas.

```
welcome.*          → Homepage (cta_title, cta_label, services_badge, etc.)
about.*            → Pagina empresa (page_title, main_subtitle, cta_title, team_badge, etc.)
contact.*          → Pagina contacto (page_badge, page_title, cta_title, cta_badge, etc.)
```

---

## Producto referencia: Personal Brand

**Core:** `personal-brand`
**Demo:** `demo-accounting-2`
**Proyecto referencia:** COKE (bp-coke)
**Módulos:** gallery, blog, projects, faqs
**Schema:** Person
**Shop products:** 7 (personal-brand, portfolio, speaker, author, personal-coach, interactive-resumes, minimalist-digital-portfolios)

Validado: provisiona correctamente, admin funcional, todas las páginas 200, defaults completos, editable end-to-end.

---

## Producto referencia: Construction-2

**Core:** `construction-2`
**Demo:** `demo-construction-2`
**Proyecto referencia:** Sur Nuevo Norte (bp-surnuevonorte)
**Online:** https://surnuevonorte.bewpro.com
**Modulos:** services, projects, gallery, blog, faqs, references (testimonials), team-members
**Schema:** HomeAndConstructionBusiness
**Shop products:** 8 (construction, construction-company, home-renovation, civil-engineering, architecture-firm, interior-construction, landscape-design, plumbing-electrical)

**Diferencias con Personal Brand:**
- Voz corporativa (3ra persona) vs personal (1ra persona)
- Modulo services activo (cards en home y about)
- CTA header ON ("Presupuesto")
- 4 counters/KPIs (en home y about)
- Team + Testimonials en about (via team_members y references)
- Split section en home (inversores extranjeros)
- Carousel de slides en hero (vs crossfade)

**Campos admin especificos:**

Tab Inicio:
- CTA header (toggle + texto + URL)
- About inline (badge + heading + texto)
- Headings de secciones (servicios badge+heading, proyectos badge+heading, CTA label)
- Split section (badge + heading + texto + texto 2)
- Links a Banner y Logos

Tab Empresa:
- Titulo + subtitulo + 2 descripciones
- 4 Counters (valor + sufijo + etiqueta)
- Team badge + titulo
- Testimonials badge + titulo
- CTA titulo + texto boton

Tab Contacto:
- Datos base (phone, email, address, hours)
- Page badge + titulo + subtitulo
- Card subtitle
- CTA badge + titulo + subtitulo
- Redes sociales

**Seeds:**
- 10 FAQs (3 categorias: Presupuestos, Proceso de Obra, Materiales y Garantia)
- 4 servicios (2 categorias: Obra Civil, Arquitectura y Diseno)
- 3 blog posts (2 categorias: Tendencias, Casos de Obra)

**Template (10 archivos):**
- Header (163 lineas), Footer (126), Page-header (48), CSS (811), JS (137)
- Welcome (356), About (234), Contact (216)
- Skin CSS (133)
- Core JSON (94)

**Overrides de modulos:**
- NO hay vistas custom por modulo (usan las base)
- Dynamic headers: 7 modulos incluyen `page-header-construction-2`
- CSS: 280 lineas de retintado (fondo beige, cards claras, textos oscuros)

Validado: 2026-04-02. Dry-run OK, DB alineada con referente online, admin funcional end-to-end, catalog mapping OK (8 shop products).
