# La Fórmula de Productos BewPro

> Doc canónico fundacional. Source of truth de cómo se compone un producto en el sistema.
> Audiencia: equipo entero — desde Coke hasta Ezequiel y Leandro.
>
> Última actualización: 2026-05-12

---

## TL;DR — La ecuación

```
                            ┌─────────────────────────────┐
                            │   PRODUCTO COMERCIAL        │
                            │   (lo que vende Ezequiel)   │
                            └─────────────────────────────┘
                                          ▲
                                          │
                                          │
  ╔═══════════════════════════════════════╧═══════════════════════════════════╗
  ║                                                                            ║
  ║  PRODUCTO COMERCIAL  =  CORE TÉCNICO  +  COPY COMERCIAL                   ║
  ║                                                                            ║
  ║  CORE TÉCNICO        =  SISTEMA  +  DEMO  +  MÓDULOS ACTIVOS              ║
  ║                                                                            ║
  ║  SITIO LIVE          =  PRODUCTO COMERCIAL  +  DATOS DEL CLIENTE          ║
  ║                                                                            ║
  ╚════════════════════════════════════════════════════════════════════════════╝
```

**En palabras**: el cliente compra un **producto comercial** (con su copy, precio, nombre). Eso resuelve a un **core técnico** (fórmula reutilizable). El core se compone de **un demo** (visual) + **módulos funcionales** (legos). Al sumar **datos del cliente**, queda el **sitio live**.

Esa ecuación es lo que hay que tener clavada en la cabeza antes de tomar cualquier decisión sobre el catálogo, pricing, o agregar nuevos productos.

---

## Las 5 capas en detalle

### Capa 1 · Sistema (la base inmutable)

Lo que NO se elige. Es el motor común a todos los proyectos BewPro:

| Componente | Qué hace | Path |
|------------|----------|------|
| Laravel 9 multitenant | 1 DB por proyecto, swap por `DB_DATABASE` en `.env` | core framework |
| Module loader | Carga `app/Modules/*` dinámicamente según core JSON | `app/Modules/`, `config/cd-system.php` |
| Config services | DB sobrescribe archivos config | `app/Services/SiteConfigService.php`, `CdSystemConfigService.php` |
| Admin panel | UI común para todos los demos (no varía por producto) | `resources/views/admin/`, `resources/views/modules/*/admin/` |
| Provisión engine | `bewpro:new`, `bewpro:provision`, `bewpro:seed` | `app/Console/Commands/` |
| Integraciones | Stripe (Cashier), Airtable, email, Slack, Tokko, reCAPTCHA | `app/Services/`, `app/Mail/` |
| Auth + RBAC | Spatie permissions (Client / Reseller / Administrator / etc.) | `database/seeders/BewProRolesPermissionsSeeder.php` |
| Helpers + skin engine | Functions para resolver demo, skin, brand defaults | `app/helpers.php` |

**Regla**: el sistema no se "decide" por producto — se mejora globalmente. Cuando se mejora, **todos los productos heredan**.

---

### Capa 2 · Demo (el "look")

Es el template visual completo. **Un sitio = 1 demo**. No se mezclan.

#### Anatomía obligatoria de un demo (8 archivos)

```
resources/views/layout/front/
├── headers/demo-{name}.blade.php           ← Navegación principal
├── footers/demo-{name}.blade.php           ← Pie de página
└── partials/page-header-{name}.blade.php   ← Banner interno (SIN prefijo "demo-")

resources/views/modules/cd-base/frontend/demos/demo-{name}/
├── welcome.blade.php                        ← Homepage
├── about.blade.php                          ← Nosotros
└── contact.blade.php                        ← Contacto

public/template/css/demos/demo-{name}.css    ← Estilos del demo
public/template/css/skins/skin-{name}.css    ← Paleta de colores (CSS custom properties)
```

#### Registros backend (4 puntos)

| Registro | Path | Para qué |
|----------|------|----------|
| Layout mapping | `app/helpers.php` → `get_demo_layout_mapping()` | Asocia demo → header/footer blades |
| Skin mapping | `app/helpers.php` → `get_demo_skin_mapping()` | Asocia demo → skin CSS |
| Page headers | `config/page-headers.php` | Mapea demo → partial name |
| Dynamic headers | 10 archivos `*/Views/.../dynamic-header.blade.php` (uno por módulo) | Cada módulo dice cómo se ve **adentro** de este demo |

#### Lo opcional (no bloquea publicación)

- JS específico del demo
- Variantes adicionales de CSS skin (ej. dark mode)
- Imágenes/assets propios en `public/cd-project/img/demos/{name}/`
- Page headers customizados por módulo

#### Demos disponibles hoy (18)

`demo-accounting-1`, `demo-accounting-2`, `demo-architecture-2`, `demo-business-consulting`, `demo-construction`, `demo-construction-2`, `demo-creative-agency-2`, `demo-creative-portfolio`, `demo-digital-agency-2`, `demo-insurance`, `demo-law-firm-2`, `demo-marketing-1`, `demo-photography-3`, `demo-product-landing`, `demo-real-estate`, `demo-restaurant`, `demo-sass`, `demo-transportation-logistic`

**Doc completa**: [product-readiness/estandar-demo.md](product-readiness/estandar-demo.md).

---

### Capa 3 · Módulos (los "legos funcionales")

Cada módulo aporta una capacidad funcional: contenido + UI + DB.

#### Anatomía de un módulo (ej. `Services`)

```
app/Modules/Services/
├── Models/                  ← Service.php, ServiceCategory.php
├── Controllers/
│   ├── Frontend/           ← Public-facing (listing + detail)
│   └── Admin/              ← Backoffice (CRUD)
├── Views/
│   ├── frontend/           ← service-page.blade.php, components/
│   └── admin/              ← Forms del CRUD
├── Routes/                  ← routes.php (frontend + admin)
└── Migrations/              ← Crea tablas en DB

resources/views/modules/services/frontend/partials/
└── dynamic-header.blade.php ← La pieza CRÍTICA: cómo se ve en CADA demo
```

#### El "dynamic-header" — el contrato demo ↔ módulo

Cada módulo tiene un `dynamic-header.blade.php` con un `@elseif` por cada demo soportado:

```blade
@if($activeDemo === 'demo-construction')
    {{-- Render Services con look construction --}}
@elseif($activeDemo === 'demo-restaurant')
    {{-- Render Services con look restaurant (probablemente "Carta" o "Menú") --}}
@endif
```

**Implicancia**: agregar un demo nuevo significa tocar los **10 archivos dynamic-header** (uno por módulo activo) para registrar cómo se ve cada módulo en ese demo.

#### Módulos vendibles hoy (11)

| Módulo | Para qué | Cores que lo usan |
|--------|----------|-------------------|
| `Blog` | Novedades / posicionamiento SEO | 13 cores |
| `Services` | Servicios del negocio | 14 cores |
| `Gallery` | Galería de imágenes | 11 cores |
| `Projects` | Portfolio de casos | 7 cores |
| `Team` (TeamMembers) | Equipo de la empresa | 3 cores |
| `References` | Testimonios | 3 cores |
| `Faqs` (en CdBase) | Preguntas frecuentes | 16 cores |
| `Menu` | Carta gastronómica | 1 core (restaurant-bar) |
| `Testimonials` | Reviews | cross-core |
| `Products` | Catálogo de productos | 3 cores |
| `Tokko` | Integración inmobiliarias | 1 core (real-estate) |

#### Módulos internos (no se venden, son infra)

`CdBase`, `Clients`, `ProjectSetup`, `Support`, `Translations`

#### Cómo "se activa" un módulo en un core

Vía el campo `modules` en el core JSON:

```json
{
  "demo": "demo-construction",
  "modules": ["services", "projects", "gallery", "blog", "faqs"],
  ...
}
```

`bewpro:new` lee este array y:
- Corre las migrations de cada módulo activo
- Habilita sus rutas
- Carga los seeds canónicos (`database/seeders/products/core/seeds/{module}-{core}.json`)

#### Sistema "alias-matrix" — copy del módulo por industria

`database/seeders/products/alias-matrix.json` define el nombre comercial que tiene cada módulo según la industria del cliente:

```
modulo: services × industria: legal       →  alias: "Áreas de Práctica"
modulo: services × industria: retail-gastro →  alias: "Especialidades"
modulo: services × industria: health-medical →  alias: "Tratamientos"
```

El mismo módulo técnico (`Services`) se renombra según contexto. Esto convierte 1 módulo en 9 productos perceptualmente distintos.

---

### Capa 4 · Core preset (la "fórmula técnica")

Es un archivo JSON que congela una combinación demo + módulos + branding defaults.

**Path**: `database/seeders/products/core/{slug}.json`

#### Estructura mínima

```json
{
  "demo": "demo-construction",
  "tagline": "Constructora",
  "description": "Plataforma para empresas constructoras",
  "modules": ["services", "projects", "gallery", "blog", "faqs"],

  "modules_navigation": {
    "services":  { "header": true,  "footer": true },
    "projects":  { "header": true,  "footer": true },
    "gallery":   { "header": true,  "footer": false },
    "blog":      { "header": true,  "footer": true },
    "faqs":      { "header": false, "footer": true }
  },

  "schema_type": "HomeAndConstructionBusiness",

  "header": {
    "cta_button": { "title": "Solicitar Presupuesto", "url": "/contact" }
  },

  "footer": { "..." },
  "seo":    { "..." },

  "brand_defaults": {
    "colors":    { "primary": "#651A38", "logo_pack": "construction" },
    "fonts":     { "primary": "Poppins", "tertiary": "Caveat" }
  }
}
```

#### Qué consume cada campo

| Campo | Lo lee… | Para… |
|-------|--------|-------|
| `demo` | Blade renderer | Saber qué header/footer/page-header/CSS cargar |
| `modules` | `bewpro:new` | Activar tablas + rutas + seeds de cada módulo |
| `modules_navigation` | Header/footer blades | Decidir si el módulo aparece en menu |
| `schema_type` | SEO meta tags | Inyectar JSON-LD apropiado (LocalBusiness, LegalService, etc.) |
| `header.cta_button` | Header blade | CTA principal arriba |
| `brand_defaults` | Skin engine | Aplicar colores/fonts cuando el cliente no tiene branding propio |
| `tagline`, `description` | Site config seeder | Texto default de welcome/SEO |

#### Inventario hoy (24 cores)

`agency`, `art-design`, `bp-dinamic`, `business-catalogue`, `catalogue-ai`, `concierge`, `construction`, `construction-2`, `corporative`, `creative-agency`, `creative-video-editor`, `financial-wealth`, `foundations-ong`, `insurance-advisor`, `law-firm-digital`, `nutritionist`, `personal-brand`, `petite-website`, `photography`, `real-estate`, `restaurant-bar`, `sitio-web-profesional`, `standard-website`, `website-reseller`

---

### Capa 5 · Shop Product (la "variante comercial")

Es la entrada que existe **en el catálogo público** de bewpro.com.

#### Composición

```
SHOP PRODUCT
├── slug (URL única)
├── name comercial ("Sitio Web para Yoga Instructor")
├── core slug (apunta a la fórmula técnica)
├── copy comercial:
│   ├── Headline   ("Yoga Instructor — listo en 48hs")
│   ├── Subheadline ("Incluye: tratamientos, especialidades...")
│   ├── Pain points (qué problema resuelve)
│   ├── Value props
│   └── CTA primary
├── tier (Básica / Profesional / Corporativa)
├── precio (desarrollo + suscripción mensual)
└── stripe_price_id (para checkout)
```

#### Source of truth para cada pieza

| Pieza | Vive en | Por qué |
|-------|---------|---------|
| Slug → core | `database/seeders/products/catalog.json` | Código rápido de leer, versionado en git |
| Copy comercial | Airtable: `Shop Products` + `Shop Products Copy` | Editable por equipo marketing sin commits |
| Precio + tier | Airtable: `Products` | Editable comercialmente |
| Stripe price_id | Stripe Dashboard + Airtable | Único source: Stripe; espejado en Airtable |

#### Ejemplo concreto: 1 core → 7 productos comerciales

El core `insurance-advisor` (demo-insurance + services + faqs) se reusa para:

```
yoga-instructor         (copy: yoga, mindfulness)
personal-trainer        (copy: fitness, entrenamiento)
chiropractor            (copy: quiropraxia, dolor)
physiotherapist         (copy: rehabilitación, lesiones)
wellness-center         (copy: holístico, bienestar)
pet-day-care-centers    (copy: mascotas, cuidado)
insurance-advisor       (copy: seguros, asesoramiento)
```

Todos **comparten la fórmula técnica** (mismo demo, mismos módulos, mismo provisioning). Lo que **varía**: nombre comercial, copy de headlines, alias de módulos por industria, y eventualmente el `schema_type` del JSON-LD.

**Esto es escalabilidad real**: una vez que el core está estable, sumar un shop product nuevo es ~30 min (copy + slug en catalog.json + record Airtable + Stripe price).

---

## El principio "legos"

### Lo que se PUEDE recombinar

| Combinación | Esfuerzo | Resultado |
|-------------|----------|-----------|
| Cualquier demo + subset de módulos = core nuevo | 2-4h (validación + seeds + checklist) | Core técnico nuevo |
| Cualquier core + copy diferente = shop product nuevo | 30 min | Producto comercial |
| Cualquier shop product + datos cliente = sitio live | 25 min (provisión auto) | Tenant nuevo |

### Lo que NO se puede recombinar

❌ **2 demos en 1 sitio**: imposible, un sitio = 1 demo (es el "look" entero).
❌ **Activar un módulo sin dynamic-header en ese demo**: rompe la vista (módulo no sabe cómo renderse).
❌ **Cambiar el core de un proyecto live**: hay que recrear (los módulos activos se commitearon en migrations).
❌ **Mezclar skins entre demos**: cada skin está hecha para su demo.

### Reglas de compatibilidad

- **Cada módulo necesita `dynamic-header.blade.php` con `@elseif` para cada demo**. Si querés activar `Menu` en un demo nuevo, hay que sumarle el `@elseif` en `app/Modules/Menu/.../dynamic-header.blade.php`.
- **Algunos módulos requieren integración propia**: `Tokko` necesita API key + skin específico; sin esa preparación no funciona.
- **El `schema_type` del core afecta SEO**: cambiar de `LocalBusiness` a `LegalService` requiere validar JSON-LD output.

---

## Cómo se escala el catálogo (costos por tipo de adición)

| Quiero agregar… | Esfuerzo | Quién | Path típico |
|-----------------|----------|-------|-------------|
| **Shop product nuevo** sobre core existente (ej. "Spa Center" sobre nutritionist) | 30 min | Coke / Ezequiel | catalog.json + Airtable copy + Stripe price |
| **Tier nuevo** (ej. agregar "Enterprise" T4) | 1-2h | Coke | docs/compania2.0/precios + Stripe + Airtable |
| **Core nuevo** sobre demo existente (ej. nuevo bundling de módulos) | 2-4h | Maxi + Coke | core/{nuevo}.json + seeds + certify |
| **Demo nuevo** (ej. demo-hotel para tourism) | 1-3 días | Frontend + Maxi | 8 blades + CSS + skin + 10 dynamic-headers + 4 registros backend |
| **Módulo nuevo** (ej. Bookings) | 3-5 días | Maxi | model + controllers + views + dynamic-headers en TODOS los demos |

**Insight comercial**: los **shop products son la palanca de escala**. Sumar 5 nuevos cada mes con copy bien hecho cuesta menos que sacar 1 demo nuevo.

---

## Validación: ¿el producto es real?

Un producto está "completo" cuando pasa los 4 bloques:

```
BLOQUE 1: TEMPLATE       (8 blades + CSS + skin + 10 dynamic-headers OK)
BLOQUE 2: PROVISIÓN      (core JSON + seeds aplican sin error)
BLOQUE 3: MARKETPLACE    (Shop Product + Copy + Price + landing visible)
BLOQUE 4: INFRAESTRUCTURA (Stripe + Airtable + email + provisioning automático)
```

Comando que mide todo en 1 línea:

```bash
php artisan bewpro:certify-product --all
```

Hoy → **9/9 productos publicados a 100/100**.

**Doc detallada de los 4 bloques**: [product-readiness/componentes.md](product-readiness/componentes.md).

---

## Diagrama de flujo: del cliente al sitio

```
   Cliente entra a bewpro.com
              │
              ▼
   /products-catalogue
              │
              ▼
   Elige Shop Product (ej. yoga-instructor, USD 350 + 25/mes)
              │
              ▼
   ┌──────────────────────────────────────────────────────┐
   │ STRIPE CHECKOUT                                       │
   │ - Pago de desarrollo + 1er mes                       │
   │ - Crea Stripe Customer                               │
   └──────────────────────────────────────────────────────┘
              │
              ▼
   ┌──────────────────────────────────────────────────────┐
   │ AIRTABLE PROJECTS (Pipeline_Status = Required)        │
   │ - Slug del shop product                              │
   │ - Customer email                                     │
   │ - Stripe customer_id                                 │
   └──────────────────────────────────────────────────────┘
              │
              ▼
   ┌──────────────────────────────────────────────────────┐
   │ CRON PROCESS-AIRTABLE (VPS1, cada 1 min)              │
   │ - Resuelve shop_slug → core_slug via catalog.json    │
   │ - Lee core/{core_slug}.json (demo + modules)         │
   │ - cPanel + DB + MySQL user                           │
   │ - git clone + composer install                       │
   │ - bewpro:new EMAIL "Título" SLUG                     │
   │   ├── corre migrations de módulos del core           │
   │   ├── aplica seeds (faqs/services/blog/etc)          │
   │   └── aplica brand_defaults (colors + fonts + skin)  │
   │ - AutoSSL Let's Encrypt                              │
   └──────────────────────────────────────────────────────┘
              │
              ▼
   {subdomain}.bewpro.com (~25 min después del pago)
              │
              ▼
   Email con credenciales → cliente edita su contenido en /admin
```

---

## Aplicaciones prácticas

### Cuando entra un lead (Cacho Buffo, Don Octavio…)

1. Pregunto rubro → busco en [catalogo-clean.md](sprint-q2/catalogo-clean.md) shop products compatibles.
2. Recomiendo el shop product → ya está el pricing armado (heredado del core/tier).
3. Sin tocar código: customer compra, pipeline auto-provisiona.

### Cuando quiero sumar producto para un nicho nuevo (ej. veterinarias)

1. ¿Hay demo apropiado? Mirar inventario de 18 demos.
2. ¿Hay core con módulos correctos? Si sí, **sumar shop product** (30 min). Si no, **crear core nuevo** sobre demo existente (2-4h).
3. Pricing: heredá el tier del core.

### Cuando quiero subir el ticket promedio

Opciones:
- **Subir tier** del shop product (Standard → Pro): cambia precio.
- **Sumar módulos** (upsell): el cliente activa Blog/Gallery/Team → sube de tier.
- **Crear core nuevo más rico**: más módulos activos = T3 natural.

### Cuando un cliente pide algo "que no tenemos"

- Si es contenido → ningún problema, lo carga en su admin.
- Si es estructura (módulo no incluido) → upsell.
- Si es **otro look** → nuevo demo (decisión más cara, evaluar volumen).

---

## Referencias técnicas

| Tema | Doc |
|------|-----|
| Estándar de un demo | [product-readiness/estandar-demo.md](product-readiness/estandar-demo.md) |
| Anatomía completa de un demo | [repo-frontend-dev/anatomia-de-un-demo.md](repo-frontend-dev/anatomia-de-un-demo.md) |
| Los 4 bloques de un producto | [product-readiness/componentes.md](product-readiness/componentes.md) |
| Vista base data-driven vs config-driven | [arquitectura-vistas-base.md](arquitectura-vistas-base.md) |
| Catálogo clean (253 productos × cores × tiers) | [sprint-q2/catalogo-clean.md](sprint-q2/catalogo-clean.md) |
| Pricing y speech de ventas | [../compania2.0/precios-y-speech-de-ventas.md](../compania2.0/precios-y-speech-de-ventas.md) |
| Cómo crear un demo nuevo | [product-readiness/guia-nuevo-demo.md](product-readiness/guia-nuevo-demo.md) |
| Estado de cada producto | [product-readiness/estado-productos.md](product-readiness/estado-productos.md) |
| Sprint Q2 — Frente Catálogo | [sprint-q2/README.md](sprint-q2/README.md) |

---

## Glosario rápido

| Término | Significa |
|---------|-----------|
| **Sistema** | El motor Laravel + infra común a todos los tenants |
| **Demo** | Template visual completo (header/footer/CSS/skin + vistas base) |
| **Skin** | Paleta de colores aplicada via CSS custom properties |
| **Módulo** | Lego funcional con modelo/views/controllers/admin |
| **Dynamic header** | El "contrato" de un módulo para integrarse a cada demo |
| **Core preset** | JSON que fija demo + módulos activos + branding defaults |
| **Shop product** | Entrada del catálogo con copy comercial, apunta a un core |
| **Tier** | Nivel de pricing (Básica / Profesional / Corporativa) |
| **Alias matrix** | Tabla de "nombre comercial del módulo según industria" |
| **Provisión** | Proceso automático de crear cPanel + DB + sitio + SSL |
| **Tenant** | Sitio de un cliente (1 DB + 1 dominio + 1 brand) |
