# Construyendo un Frontend Antes de que la API esté lista: Sin accesorios Brittle

<datetime class="hidden">2025-12-13T14:30</datetime>

<!--category-- ASP.NET Core, LLM, API Development, Testing, Mock APIs -->
## Introducción

¿Cuántas veces has estado bloqueado esperando que las API de backend estén listas? ¿O has pasado horas manteniendo datos simulados que se vuelven rancios en el momento en que cambian los requisitos?

Entrar `mostlylucid.mockllmapi` - una plataforma de burla ASP.NET Core lista para la producción que utiliza modelos de lenguaje grande para generar respuestas API realistas y contextualmente conscientes sobre la marcha. En lugar de mantener los accesorios JSON, usted obtiene burlas inteligentes que se adaptan a sus peticiones y recordar estado a través de llamadas.

**Lo que apoya:** Cada protocolo que necesita: REST, GraphQL, gRPC, SignalR, Server-Sent Events y OpenAPI. A diferencia de los dispositivos estáticos, las respuestas se generan dinámicamente en función del contexto de solicitud, haciendo que los flujos de trabajo de varios pasos y los escenarios de pruebas complejos sean triviales.

### Enlaces al proyecto

[![NuGet](https://img.shields.io/nuget/v/mostlylucid.mockllmapi.svg)](https://www.nuget.org/packages/mostlylucid.mockllmapi)
[![NuGet](https://img.shields.io/nuget/dt/mostlylucid.mockllmapi.svg)](https://www.nuget.org/packages/mostlylucid.mockllmapi)
[![Liberación de GitHub](https://img.shields.io/github/v/release/scottgal/LLMApi)](https://github.com/scottgal/LLMApi/releases)
[![Licencia: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/)

- **Repositorio:** [https://github.com/scottgal/LLMApi](https://github.com/scottgal/LLMApi)
- **Liberaciones:** https://github.com/scottgal/LLMApi/releases
- **Paquete de acompañantes:** [mayormente lucid.mockllmapi.Testing](https://github.com/scottgal/LLMApi/blob/master/mostlylucid.mockllmapi.Testing/README.md) - Pruebas de utilidades con integración fluida de HttpClient

### Tres maneras de usarlo

Usted puede utilizar principalmentelucid.mockllmapi de tres maneras, dependiendo de lo aislado que desee que su entorno dev sea:

1. **Paquete ASP.NET Core NuGet** - Añadir a sus proyectos existentes
2. **Herramienta CLI independiente** - Executable entre plataformas (descargar desde [liberaciones](https://github.com/scottgal/LLMApi/releases))
3. **Contenedor Docker** - Cero instalación requerida

[TOC]

## La característica del asesino: Memoria de contexto

> **Guía completa:** [Documentación de contextos API](https://github.com/scottgal/LLMApi/blob/master/docs/API-CONTEXTS.md)

Las API simuladas tradicionales tienen un defecto fatal: cada solicitud es independiente. Consigue un usuario con ID 42, luego consigue sus pedidos, y recibirás pedidos para ID 99. Sin consistencia.

**Contextos de la API** resolver esto con memoria compartida a través de peticiones relacionadas:

```javascript
// Request 1: Get a user
// Note: 'context' is a simple query parameter - no cookies or sessions needed
fetch('/api/users/123?context=checkout-session')
// Response: { id: 42, name: "Alice Smith", email: "alice@example.com" }

// Request 2: Get orders (same context parameter)
fetch('/api/orders?userId=42&context=checkout-session')
// Response: { userId: 42, customerName: "Alice Smith", items: [...] }
// Perfect! Same user, consistent data
```

El LLM ve solicitudes anteriores en el mismo contexto y genera datos consistentes. **Este es el cambiador de juego para flujos de trabajo de varios pasos.**

**Características:**

**Ciclo de vida:**

- Expiración automática después de 15 minutos de inactividad (configurable)
- Cada solicitud actualiza el temporizador

**Comportamiento:**

- Extracción inteligente de TODOS los campos de las respuestas

**Seguridad:**

- Cero fugas de memoria - los contextos se limpian

**Casos de uso:**

- Perfecto para CI/CD - no hay estado entre carreras

## Inicio rápido

### Opción 1: Paquete NuGet

```bash
dotnet add package mostlylucid.mockllmapi
```

```csharp
// Program.cs
builder.Services.AddLLMockApi(builder.Configuration);
app.MapLLMockApi("/api/mock");
```

### Opción 2: Herramienta CLI

```bash
# Download from https://github.com/scottgal/LLMApi/releases
llmock serve --port 5000
```

### Opción 3: Docker

> **Guía completa:** [Guía de implementación de Docker](https://github.com/scottgal/LLMApi/blob/master/docs/DOCKER_GUIDE.md)

```bash
git clone https://github.com/scottgal/LLMApi.git
cd LLMApi
docker compose up -d
```

### Requisitos previos: motor LLM

Necesitas **uno de los**: Ollama, OpenAI, o LM Studio:

```bash
# Recommended: Ollama with ministral-3:3b (ultra-fast, accurate JSON generation)
ollama pull ministral-3:3b
```

Ver [Guía de modelos de Ollama](https://github.com/scottgal/LLMApi/blob/master/docs/OLLAMA_MODELS.md) para todas las recomendaciones y comparaciones del modelo.

### Inténtalo inmediatamente

Una vez en ejecución, haga su primera petición:

```bash
curl http://localhost:5000/api/mock/users
# Response: [{"id": 1, "name": "Alice Johnson", "email": "alice@example.com"}, ...]
```

¡Eso es todo! Ahora tienes una API simulada que genera datos realistas bajo demanda.

## Ejemplo real: Buscar en su mayoríalucid.net

Aquí está el código de búsqueda real de este blog - **este es el código de salida de producción sin cambios**, no se necesitan adaptaciones para el simulacro:

```javascript
// typeahead.js from mostlylucid.net
export function typeahead() {
    return {
        query: '',
        results: [],
        search() {
            fetch(`/api/search/${encodeURIComponent(this.query)}`)
                .then(response => response.json())
                .then(data => { this.results = data; });
        }
    }
}
```

**Muérdelo:**

```bash
# Using CLI
llmock serve --port 5000

# Query returns contextual results
curl http://localhost:5000/api/search/markdown
# LLM generates blog posts about Markdown

curl http://localhost:5000/api/search/docker
# LLM generates blog posts about Docker
```

Cada respuesta es única y realista, adaptándose a la consulta.

## Control de forma: Definir su esquema

Más allá de sólo generar datos aleatorios, a menudo necesita un control preciso sobre la estructura JSON. El control de forma le permite decirle al LLM exactamente qué estructura generar - la característica más poderosa para el desarrollo de frontend.

### Forma básica

```bash
# Without shape - random structure
curl http://localhost:5000/api/mock/users
# Response: { "userId": 1, "fullName": "Alice" }

# With shape - you control it
curl "http://localhost:5000/api/mock/users" \
  -H 'X-Response-Shape: {"id":0,"name":"string","email":"string"}'
# Response: { "id": 1, "name": "Alice", "email": "alice@example.com" }
```

**Tres formas de especificar la forma:**

1. Parámetro de consulta - `?shape={...}`
2. Encabezado HTTP - `X-Response-Shape: {...}` (recomendado)
3. Órgano de solicitud - `{"shape": {...}}`

### Forma anidada

```javascript
const shape = {
  company: {
    id: 0,
    name: "string",
    employees: [{
      id: 0,
      firstName: "string",
      department: { id: 0, name: "string" },
      projects: [{ id: 0, title: "string" }]
    }]
  }
};

fetch('/api/mock/company', {
  headers: { 'X-Response-Shape': JSON.stringify(shape) }
});
```

### Alineación de TypeScript

```typescript
interface User {
  id: number;
  name: string;
  email: string;
}

const USER_SHAPE: Partial<User> = { id: 0, name: "", email: "" };

// Shape becomes your type definition AND mock schema!
```

## Flujos de trabajo de varios pasos con contexto

Ahora combinemos el control de forma con contextos API para manejar flujos de trabajo complejos y de varios pasos. ¿Recuerda la característica de memoria de contexto de antes? Así es como brilla en operaciones asíncronas del mundo real.

Este ejemplo del servicio de traducción de mayoritariamentelucid.net muestra cómo el LLM mantiene el estado a través de un flujo de trabajo completo asíncrono:

```bash
# Step 1: Start translation
curl -X POST http://localhost:5000/api/translate/start?context=translate-session \
  -d '{"language": "es", "markdown": "# Hello World"}'
# Response: { "taskId": "abc-123", "status": "processing" }

# Step 2: Check status (LLM remembers the task)
curl http://localhost:5000/api/translate/status/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "status": "complete" }

# Step 3: Get result (same taskId!)
curl http://localhost:5000/api/translate/result/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "translatedText": "# Hola Mundo" }
```

Note cómo `taskId` es consistente en todas las solicitudes. **El contexto lo hace posible.**

## Más allá del REST: Todos los Protocolos

Hasta ahora nos hemos centrado en el REST, pero las aplicaciones modernas necesitan más. Ya sea que esté construyendo con GraphQL, implementando funciones en tiempo real con SignalR, o trabajando con los servicios de gRPC, en su mayoría lucid.mockllmapi lo tiene cubierto.

**Protocolos compatibles:**

- ✓ REST
- ✓ GraphQL
- ✓ gRPC
- ✓ SeñalR
- ✓ Eventos de envío de servidores (SSE)
- ✓ OpenAPI / Swagger

### GráficaQL

> **Guía:** [Sección GráficaQL](https://github.com/scottgal/LLMApi#graphql-api-mocking)

```bash
curl -X POST http://localhost:5000/api/mock/graphql \
  -d '{"query": "{ users { id name email } }"}'
```

La consulta ES la forma - no se necesita un esquema separado.

### gRPC

> **Guía completa:** [Soporte gRPC](https://github.com/scottgal/LLMApi/blob/master/docs/GRPC_SUPPORT.md)

```bash
# Upload .proto file
curl -X POST http://localhost:5116/api/grpc-protos \
  --data-binary "@user_service.proto"

# Call via JSON or binary Protobuf
curl -X POST http://localhost:5116/api/grpc/userservice/UserService/GetUser \
  -d '{"user_id": 123}'
```

### SeñalR en tiempo real

> **Guía:** [Guía de demostración de SignalR](https://github.com/scottgal/LLMApi/blob/master/SIGNALR_DEMO_GUIDE.md)

```javascript
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hub/mock")
    .build();

connection.on("DataUpdate", (message) => {
    console.log(message.data); // Live generated data
});

await connection.start();
await connection.invoke("SubscribeToContext", "stock-prices");
```

Perfecto para el prototipado del salpicadero.

### Eventos de envío de servidores (SSE)

> **Guía:** [Modos de transmisión SSE](https://github.com/scottgal/LLMApi/blob/master/docs/SSE_STREAMING_MODES.md)

```javascript
const eventSource = new EventSource('/api/mock/stream/users');
eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Token:', data.chunk); // Progressive generation
};
```

### OpenAPI / Swagger

> **Guía completa:** [Características de OpenAPI](https://github.com/scottgal/LLMApi/blob/master/docs/OPENAPI-FEATURES.md)

```bash
# CLI: Load any OpenAPI spec
llmock serve --spec https://petstore3.swagger.io/api/v3/openapi.json

# All endpoints become live mocks automatically
curl http://localhost:5000/petstore/pet/123
```

## Herramientas enchufables: Mix Real & Mock Data

> **Guía completa:** [Herramientas y acciones](https://github.com/scottgal/LLMApi/blob/master/docs/TOOLS_ACTIONS.md)

A veces necesita un enfoque híbrido - datos reales de la producción combinada con datos simulados generados. El sistema de herramientas pluggable le permite llamar APIs reales durante la generación de simulacros, creando escenarios de prueba increíblemente realistas.

```json
{
  "Tools": [{
    "Name": "getUserData",
    "Type": "http",
    "HttpConfig": {
      "Endpoint": "https://api.production.com/users/{userId}",
      "Headers": { "Authorization": "Bearer ${PROD_API_KEY}" }
    }
  }]
}
```

```bash
curl "http://localhost:5000/api/mock/orders?useTool=getUserData&userId=123"
```

La maqueta obtiene datos de usuario REAL, luego el LLM genera órdenes usándolos. **Extremadamente útil para pruebas realistas con flujos de trabajo híbridos simulados/reales.**

## Integración básica de ASP.NET

Si está construyendo con ASP.NET Core, la integración es perfecta. La belleza de este enfoque es **cambios de código cero** a sus servicios - usted simplemente configura `HttpClient` para señalar el simulacro durante el desarrollo y en la API real en la producción.

```csharp
// Real code from mostlylucid.net
builder.Services.AddHttpClient<IMarkdownTranslatorService, MarkdownTranslatorService>(
    client => {
        var baseUrl = builder.Configuration["TranslationService:BaseUrl"]
            ?? "http://localhost:5000";  // Mock during dev
        client.BaseAddress = new Uri(baseUrl);
    }
);
```

**appsettings.Development.json:**

```json
{
  "TranslationService": {
    "BaseUrl": "http://localhost:5000"  // Mock
  }
}
```

**appsettings.Production.json:**

```json
{
  "TranslationService": {
    "BaseUrl": "https://api.production.com"  // Real
  }
}
```

Este patrón funciona para cualquier `HttpClient` en tu aplicación - servicios de traducción, pasarelas de pago, APIs externas, lo nombras.

## Cuándo usar esto

Antes de sumergirnos en funciones avanzadas, vamos a ser claros sobre cuándo esta herramienta tiene sentido para su flujo de trabajo.

**Perfecto para:**

- **Desarrollo de la interfaz antes de que exista el motor** - Deja de bloquear en los equipos de backend.
- **Pruebas de flujo de trabajo de varios pasos** - Memoria de contexto maneja escenarios complejos
- **Prototipado API** - Experimente con formas de respuesta antes de comprometerse
- **Desarrollo fuera de línea** - Trabajar sin dependencias de red
- **Ensayo de hipótesis de error** - Simular fallos sin romper la producción
- **Gasoductos CI/CD** - Ninguna dependencia externa significa construcciones más rápidas y fiables

**No es ideal para:**

- **Entornos de producción** - Esta es una herramienta de desarrollo y pruebas
- **Datos de los ensayos determinísticos** - Utilice accesorios cuando necesite una reproducibilidad exacta
- **Ensayos de contratos** - Validar siempre contra API reales para contratos de producción

Ahora que sabes dónde encaja, exploremos las capacidades avanzadas.

## Características avanzadas

> Estas características son opcionales - se puede obtener un valor tremendo de lo básico por sí solo. Pero cuando se necesita realismo de grado de producción a escala, estas herramientas están aquí.

### Múltiples motores LLM

> **Guía:** [Múltiples motores LLM](https://github.com/scottgal/LLMApi/blob/master/docs/MULTIPLE_LLM_BACKENDS.md)

```bash
# Fast for dev
curl http://localhost:5000/api/mock/users

# High quality for demos
curl "http://localhost:5000/api/mock/users?backend=quality"

# Cloud AI for production-like
curl "http://localhost:5000/api/mock/users?backend=openai"
```

### Simulación de limitación de velocidad

> **Guía:** [Limitación de velocidad y bateo](https://github.com/scottgal/LLMApi/blob/master/docs/RATE_LIMITING_BATCHING.md)

Pruebe cómo su aplicación maneja los límites de velocidad:

```json
{
  "EnableRateLimiting": true,
  "RateLimitDelayRange": "500-2000"
}
```

### Simulación de errores

```bash
# Test 429 rate limiting
curl "http://localhost:5000/api/mock/users?error=429&errorMessage=Rate%20limit%20exceeded"

# Test 503 unavailable
curl "http://localhost:5000/api/mock/users?error=503"
```

Soporta todos los códigos 4xx y 5xx.

### Caché de respuesta

```bash
# Generate and cache 10 variants
curl "http://localhost:5000/api/mock/users?shape={\"$cache\":10,\"id\":0,\"name\":\"string\"}"
```

Las solicitudes posteriores reciben respuestas en caché instantáneas.

## Pruebas de Utilidades: mayormente lucid.mockllmapi.Testing

> **Paquete:** [mayormente lucid.mockllmapi.Testing](https://github.com/scottgal/LLMApi/blob/master/mostlylucid.mockllmapi.Testing/README.md)

Todas las características anteriores son ideales para el desarrollo, pero ¿qué pasa con las pruebas automatizadas? El paquete de pruebas acompañante proporciona una API fluida que hace las pruebas de integración una brisa - configurar el comportamiento simulado de manera declarativa y dejar que `HttpClient` Haz el resto.

### Instalación

```bash
dotnet add package mostlylucid.mockllmapi.Testing
```

### Uso básico

```csharp
using mostlylucid.mockllmapi.Testing;

// Create a client with a single endpoint configuration
var client = HttpClientExtensions.CreateMockLlmClient(
    baseAddress: "http://localhost:5116",
    pathPattern: "/users",
    configure: endpoint => endpoint
        .WithShape(new { id = 0, name = "", email = "" })
        .WithCache(5)
);

// Make requests - configuration is automatically applied
var response = await client.GetAsync("/users");
var users = await response.Content.ReadFromJsonAsync<User[]>();
```

### Múltiples puntos finales

```csharp
var client = HttpClientExtensions.CreateMockLlmClient(
    "http://localhost:5116",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" })
            .WithCache(10))
        .ForEndpoint("/posts", config => config
            .WithShape(new { id = 0, title = "", content = "", authorId = 0 })
            .WithCache(20))
        .ForEndpoint("/error", config => config
            .WithError(404, "Resource not found"))
);

// Each endpoint automatically uses its configuration
var usersResponse = await client.GetAsync("/users");
var postsResponse = await client.GetAsync("/posts");
var errorResponse = await client.GetAsync("/error"); // Returns 404
```

### Opciones de configuración

**Configuración de la forma:**

```csharp
// Using anonymous objects
.WithShape(new { id = 0, name = "", active = true })

// Using JSON strings
.WithShape("{ \"id\": 0, \"name\": \"\", \"tags\": [] }")

// Complex nested structures
.WithShape(new
{
    user = new { id = 0, name = "" },
    posts = new[] { new { id = 0, title = "" } }
})
```

**Simulación de errores:**

```csharp
// Simple error
.WithError(404)

// With custom message
.WithError(404, "User not found")

// With details
.WithError(422, "Validation failed", "Email address is invalid")
```

**Streaming:**

```csharp
// Enable streaming with token-by-token output
.WithStreaming()
.WithSseMode("LlmTokens")

// Stream complete objects
.WithStreaming()
.WithSseMode("CompleteObjects")

// Stream array items individually
.WithStreaming()
.WithSseMode("ArrayItems")
```

### Inyección por dependencia

**Cliente tecleado:**

```csharp
services.AddMockLlmHttpClient<IUserApiClient>(
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" }))
);
```

**Nombre del cliente:**

```csharp
services.AddMockLlmHttpClient(
    name: "MockApi",
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/data", config => config
            .WithShape(new { value = 0 }))
);

// Usage
var client = httpClientFactory.CreateClient("MockApi");
```

### Ejemplo de pruebas de integración

```csharp
[Fact]
public async Task Should_Handle_User_Creation()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users",
        config => config
            .WithMethod("POST")
            .WithShape(new { id = 0, name = "", email = "", createdAt = "" })
    );

    // Act
    var newUser = new { name = "John Doe", email = "john@example.com" };
    var response = await client.PostAsJsonAsync("/users", newUser);

    // Assert
    response.EnsureSuccessStatusCode();
    var created = await response.Content.ReadFromJsonAsync<User>();
    Assert.NotNull(created);
    Assert.NotEqual(0, created.Id);
}

[Fact]
public async Task Should_Handle_Not_Found_Error()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users/999",
        config => config.WithError(404, "User not found")
    );

    // Act
    var response = await client.GetAsync("/users/999");

    // Assert
    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
```

### Cómo funciona

Los `MockLlmHttpHandler` es una `DelegatingHandler` que:

1. Intercepta las solicitudes HTTP salientes
2. Coincide con las peticiones contra los patrones de endpoint configurados
3. Inyecta configuración simulada a través de parámetros de consulta y encabezados HTTP
4. Reenvía la solicitud modificada a la API de LLM simulada real

Esto le permite utilizar un real `HttpClient` en sus pruebas mientras controla fácilmente el comportamiento de la API simulada sin modificar el código de la aplicación.

## Mejores prácticas y consejos

Después de trabajar con esta herramienta en múltiples proyectos, aquí están los patrones que funcionan mejor:

1. **Usar siempre contextos para flujos de trabajo** - Garantiza identificaciones y datos consistentes a través de operaciones multi-paso
2. **Forma de uso para la seguridad del tipo** - Haz que coincida con tus interfaces TypeScript
3. **Mezclar datos reales y simulados con herramientas** - Lo mejor de ambos mundos
4. **Elija el modelo correcto** (véase [Guía de modelos de Ollama](https://github.com/scottgal/LLMApi/blob/master/docs/OLLAMA_MODELS.md) Para más detalles:
   - **RECOMENDADO PARA EL DEV**: `ministral-3:3b` (3B params, 32K context) - **¡Matar a JSON!** RAM ultrarrápida, altamente precisa y mínima
   - **Producción-como**: `llama3` (8B params, 8K context) - El mejor equilibrio de calidad y rendimiento
   - **Alta calidad**: `mistral-nemo` (12B params, 128K context) - Esquemas complejos y conjuntos de datos masivos
   - **Recursos limitados**: `gemma3:4b` o `phi3` - Alternativas más ligeras

## Documentación completa

- **[Repositorio principal](https://github.com/scottgal/LLMApi)** - Fuente y panorama general
- **[Referencia de configuración](https://github.com/scottgal/LLMApi/blob/master/docs/CONFIGURATION_REFERENCE.md)** - Todos los ajustes
- **[Guía de contextos de API](https://github.com/scottgal/LLMApi/blob/master/docs/API-CONTEXTS.md)** - Memoria de contexto inmersión profunda
- **[Herramientas y acciones](https://github.com/scottgal/LLMApi/blob/master/docs/TOOLS_ACTIONS.md)** - Integración API externa
- **[Características de OpenAPI](https://github.com/scottgal/LLMApi/blob/master/docs/OPENAPI-FEATURES.md)** - Escarnio basado en especificaciones
- **[Soporte gRPC](https://github.com/scottgal/LLMApi/blob/master/docs/GRPC_SUPPORT.md)** - Buffers de protocolo
- **[Guía Docker](https://github.com/scottgal/LLMApi/blob/master/docs/DOCKER_GUIDE.md)** - Despliegue de contenedores
- **[Múltiples motores](https://github.com/scottgal/LLMApi/blob/master/docs/MULTIPLE_LLM_BACKENDS.md)** - Configuración de múltiples proveedores
- **[Limitación de la tasa](https://github.com/scottgal/LLMApi/blob/master/docs/RATE_LIMITING_BATCHING.md)** - Simular límites
- **[Paquete de pruebas](https://github.com/scottgal/LLMApi/blob/master/mostlylucid.mockllmapi.Testing/README.md)** - Utilidades HttpClient

## Conclusión

El desarrollo de Frontend no tiene que esperar a las API de backend. `mostlylucid.mockllmapi` le da:

- **Memoria de contexto** - Datos consistentes y confiables a través de flujos de trabajo de varios pasos
- **Control de forma** - Definiciones precisas de esquemas que coincidan con sus tipos
- **Apoyo al protocolo universal** - REST, GraphQL, GRPC, SignalR, SSE, OpenAPI
- **Ensayos híbridos** - Mezclar datos de producción reales con simulacros generados
- **Mantenimiento cero** - No hay accesorios JSON para actualizar cuando cambian los requisitos
- **Utilidades de ensayo** - API de fluidez para pruebas de integración

¿La diferencia entre esto y la burla tradicional? Su interfaz funciona contra datos realistas, contextualmente conscientes desde el primer día. No más "funcionó con datos simulados pero falló con datos reales" sorpresas.

Ya sea que estés construyendo un blog simple o una aplicación empresarial compleja, iterarás más rápido, probarás más a fondo y enviarás con confianza.

**¿Listo para empezar?**

```bash
docker compose up -d
```

Eso es, no se requiere motor.