# Mercado Minero — Diseño Fase 1: Catálogo del Marketplace

- **Fecha:** 2026-06-03
- **Estado:** Aprobado (diseño) — pendiente de plan de implementación
- **Origen:** Recreación local de https://www.mercadominero.com/ (no se dispone del código fuente original; se reconstruye desde cero, inspirado en el sitio real con mejoras).

## 1. Objetivo y alcance

Construir, desde cero y corriendo en `http://localhost:3000`, la **primera versión funcional** del marketplace minero B2B de Mercado Minero. La Fase 1 se enfoca en el **catálogo de oportunidades** (activos mineros): explorar, filtrar y ver el detalle de publicaciones leídas desde una base de datos.

El sitio real hoy tiene poblado únicamente el catálogo de **activos**; Inversionistas, Cómo funciona, Productos y Servicios están en estado "Próximamente". La Fase 1 replica ese estado.

### Dentro de alcance (Fase 1)
- Home / landing pública.
- Catálogo `/marketplace` con filtros, orden y grilla de tarjetas (vista Lista).
- Detalle de oportunidad `/marketplace/[slug]`.
- Páginas "Próximamente" para Inversionistas, Cómo funciona, Productos y Servicios.
- Base de datos con datos semilla (~13 oportunidades reales).

### Fuera de alcance (fases siguientes)
- Autenticación / cuentas de usuario (login, registro).
- Asistente de publicación de anuncios (`/dashboard/publicar-activo`).
- Vista de Mapa real interactiva (se incluye solo si alcanza; si no, queda para Fase 2).
- Selector de idioma funcional (solo español por ahora).
- Contacto / mensajería entre comprador y vendedor.
- Sección Inversionistas y Cómo funciona con contenido completo.

## 2. Stack técnico

- **Next.js 15** (App Router) + **TypeScript** + **React Server Components**.
- **Tailwind CSS** para estilos.
- **Prisma ORM** con **SQLite** en desarrollo local (archivo `dev.db`). Esquema portable a **PostgreSQL** para producción (se cambia el `provider` y la `DATABASE_URL`).
- Script de **seed** en TypeScript para poblar datos de ejemplo.
- Pruebas: **Vitest** (unitarias de la capa de datos y parseo de filtros).
- Arranque local: `npm install` → `npx prisma migrate dev` → `npm run db:seed` → `npm run dev`.

> Decisión de base de datos: SQLite en local elimina toda fricción de instalación en macOS y corre al instante; el mismo esquema Prisma migra a PostgreSQL al desplegar.

## 3. Identidad visual

Tomada de las capturas reales del sitio (`/Capturas`), tema oscuro con acento ámbar:

- **Fondo:** azul-noche muy oscuro (`#0b1220` aprox.); superficies/tarjetas un tono más claro (`#131c2b` aprox.).
- **Acento:** ámbar/naranja (`#f59e0b` aprox.) para CTAs, precios, enlaces activos y "Latinoamérica".
- **Texto:** blanco para titulares, gris pizarra (`#94a3b8` aprox.) para secundario.
- **Etiquetas kicker:** mayúsculas, tracking amplio, color ámbar.
- **Logo:** ícono de montaña + wordmark "MERCADO MINERO" en ámbar.
- **Estilo general:** corporativo B2B, limpio, denso en información, profesional.

## 4. Modelo de datos (Prisma)

### `Listing` (oportunidad)
| Campo | Tipo | Notas |
|---|---|---|
| `id` | String (cuid) | PK |
| `slug` | String único | para URL `/marketplace/[slug]` |
| `title` | String | título de la oportunidad |
| `description` | String (largo) | descripción completa |
| `category` | Enum `Category` | ACTIVO, PRODUCTO, SERVICIO |
| `assetType` | Enum `AssetType?` | tipo de activo |
| `stage` | Enum `Stage?` | etapa del proyecto |
| `country` | String | ej. "CL", "AR" |
| `region` | String? | región/provincia |
| `city` | String? | ciudad/comuna |
| `lat` | Float? | latitud (para mapa futuro) |
| `lng` | Float? | longitud |
| `priceUsd` | BigInt? | precio en USD |
| `surfaceHa` | Float? | superficie en hectáreas |
| `concessionCount` | Int? | nº de concesiones |
| `verified` | Boolean | default false |
| `imageUrl` | String? | imagen de portada |
| `publishedAt` | DateTime | default now |
| `dealTypes` | relación `ListingDealType[]` | estructura(s) de trato |
| `commodities` | relación `ListingCommodity[]` | minerales (Au, Cu, Ag…) |

### Tablas de relación (portables a SQLite y Postgres)
- `ListingCommodity` (`listingId`, `commodity: Enum Commodity`, `isPrimary: Boolean`).
- `ListingDealType` (`listingId`, `dealType: Enum DealType`).

### Enums (valores reales observados en el asistente de publicación)
- **Category:** `ACTIVO`, `PRODUCTO`, `SERVICIO`.
- **AssetType:** `TERRENO_PROYECTO`, `CONCESION_MINERA`, `RELAVE_RIPIO_ESCORIA`, `INFRAESTRUCTURA_PLANTA`.
- **Stage:** `PROSPECCION`, `EXPLORACION_BASICA`, `EXPLORACION_AVANZADA`, `PRE_DESARROLLO`, `PRODUCCION`.
- **DealType:** `ADQUISICION`, `VENTA_100`, `VENTA_PARCIAL`, `EARN_IN`, `FARM_IN`, `ROYALTY`, `OPCION_COMPRA`, `OFF_TAKE`, `SPIN_OUT`, `ARRIENDO`, `PARTICIPACION_ACCIONARIA`, `ACUERDO_TRIBUTO`, `ALIANZA_ESTRATEGICA`.
- **Commodity:** `AU`, `AG`, `CU`, `PB`, `ZN`, `MN`, `V`, `LI`, `FE`, `CO`, `NI`, `SN`, `W`, `MO`, `U`, `COAL`, `OTRO`.

## 5. Rutas y páginas

| Ruta | Descripción |
|---|---|
| `/` | Home: hero, stats, "Tres mercados", "Dos lados", CTA, footer suscripción. |
| `/marketplace` | Catálogo: barra de stats, filtros, orden, grilla de tarjetas (vista Lista). Filtros vía query params en el servidor. |
| `/marketplace/[slug]` | Detalle de la oportunidad. |
| `/inversionistas` | Página "Próximamente". |
| `/como-funciona` | Página "Próximamente". |
| `/marketplace/productos` | Página "Próximamente: productos minerales". |
| `/marketplace/servicios` | Página "Próximamente". |

## 6. Componentes (responsabilidad única)

- `Header` — logo, navegación, botón Publicar (decorativo en Fase 1), ES, avatar.
- `Footer` — bloque "Suscríbete para recibir avisos" + enlaces + copyright.
- `Hero`, `StatsBand`, `MarketsSection`, `TwoSidesSection`, `CtaBand` — secciones de la home.
- `FilterBar` — filtros del catálogo; lee/escribe query params.
- `ListingGrid` — grilla de resultados.
- `ListingCard` — tarjeta individual.
- `CommodityBadge`, `StageBadge`, `DealTypeBadge`, `PriceTag`, `VerifiedBadge` — átomos visuales.
- `ComingSoon` — plantilla reutilizable para páginas "Próximamente".
- `lib/listings.ts` — capa de acceso a datos: `getListings(filters)`, `getListingBySlug(slug)`, `getMarketStats()`.
- `lib/filters.ts` — parseo y validación de filtros desde `searchParams` a un objeto tipado.

## 7. Filtros del catálogo

Leídos de los query params de la URL (filtrado en el servidor, sin estado de cliente):
- `tipo` (categoría / tipo de activo)
- `negocio` (estructura de trato / DealType)
- `commodity`
- `pais`
- `precioMin`, `precioMax`
- `superficieMin`, `superficieMax`
- `verificados` (boolean "solo verificados")
- `orden` (default: `recientes`)

`lib/filters.ts` convierte estos params en un `ListingFilter` tipado; `getListings` lo traduce a un `where` de Prisma. Valores inválidos se ignoran de forma segura.

## 8. Flujo de datos

Server Components → `lib/listings.ts` → Prisma → SQLite. La página `/marketplace` recibe `searchParams`, los pasa a `lib/filters.ts`, obtiene el `ListingFilter` y consulta. No hay fetching del lado del cliente en la Fase 1. El detalle usa `getListingBySlug`; si no existe, `notFound()`.

## 9. Manejo de errores y estados

- **Sin resultados:** estado vacío con mensaje y opción de limpiar filtros.
- **Slug inexistente:** `not-found.tsx` (404).
- **Carga:** `loading.tsx` con esqueletos donde aplique.
- **Datos faltantes** (precio/superficie nulos): la tarjeta degrada con elegancia ("Precio a consultar").

## 10. Datos semilla (~13 oportunidades)

Basados en las publicaciones reales observadas (Chile/Argentina), sumando ≈ US$705M. Ejemplos:
- Proyecto Cerro del Viento — Ag–Au epitermal, Macizo del Deseado, Santa Cruz (AR).
- Proyecto Veta Esperanza — Cu–Au IOCG, Combarbalá, Coquimbo (CL).
- Proyecto La Laura — Au, Cu, Ag, Vicuña, Coquimbo (CL).
- Concesión de Explotación Cu–Au en Canela (Choapa), 90 ha (CL).
- Proyecto Cu–Au en Canela (Choapa), 100 ha (CL).
- Proyecto Cu–Au IOCG Canela Baja, Coquimbo (CL).
- Cobre de alta ley en Chile Central (Petorca), 817 ha (CL).
- (…hasta ~13, con etapa, commodities, precio, superficie y tipo de trato variados.)

## 11. Pruebas (TDD)

- `lib/filters.ts`: parseo de query params válidos/ inválidos → `ListingFilter` correcto.
- `lib/listings.ts`: `getListings` aplica filtros (commodity, país, rango de precio, verificados, orden) sobre datos semilla en una DB de prueba.
- `getListingBySlug`: devuelve la oportunidad correcta / null.
- Prueba de humo: la página `/marketplace` renderiza tarjetas con datos semilla.

## 12. Puesta en marcha (local)

```bash
npm install
npx prisma migrate dev --name init
npm run db:seed
npm run dev   # http://localhost:3000
```

## 13. Criterios de éxito de la Fase 1

1. El sitio levanta en `http://localhost:3000` sin errores.
2. La home muestra hero, stats, secciones de mercados y footer fieles a la identidad real.
3. `/marketplace` lista las ~13 oportunidades semilla en tarjetas y los filtros (commodity, país, precio, verificados) y el orden funcionan.
4. El detalle de cada oportunidad es accesible por slug.
5. Las páginas "Próximamente" existen y son navegables.
6. Las pruebas unitarias pasan.
