Author: Dominicode

  • Angular v22 + Vercel AI SDK: streaming de IA con Signals

    Angular v22 + Vercel AI SDK: streaming de IA con Signals

    ANTHROPIC_API_KEY=sk-ant-xxxxxxxx

    
    ---
    
    ## Paso 1: El servidor backend con streamText
    
    Crea un archivo `server/chat.ts` fuera del proyecto Angular (o en un monorepo aparte). Este servidor tiene un solo endpoint: recibe mensajes, llama a Claude, y hace streaming de la respuesta.
    
    ```typescript
    // server/chat.ts
    import { streamText } from 'ai';
    import { anthropic } from '@ai-sdk/anthropic';
    
    const server = Bun.serve({
      port: 3000,
      async fetch(req) {
        // CORS para desarrollo local
        if (req.method === 'OPTIONS') {
          return new Response(null, {
            headers: {
              'Access-Control-Allow-Origin': '*',
              'Access-Control-Allow-Methods': 'POST, OPTIONS',
              'Access-Control-Allow-Headers': 'Content-Type',
            },
          });
        }
    
        if (req.method === 'POST' && new URL(req.url).pathname === '/api/chat') {
          const { messages } = await req.json();
    
          const result = streamText({
            model: anthropic('claude-sonnet-4-6'),
            system: 'Eres un asistente técnico especializado en Angular y desarrollo frontend moderno. Responde en español de forma concisa y directa.',
            messages,
          });
    
          return result.toTextStreamResponse({
            headers: {
              'Access-Control-Allow-Origin': '*',
            },
          });
        }
    
        return new Response('Not found', { status: 404 });
      },
    });
    
    console.log(`Servidor corriendo en http://localhost:${server.port}`);
    

    Arrancar el servidor:

    bun run server/chat.ts
    

    streamText de la AI SDK devuelve un objeto con varios métodos. toTextStreamResponse() genera una Response HTTP estándar con Content-Type: text/plain; charset=utf-8 y Transfer-Encoding: chunked — exactamente lo que necesita el cliente para consumir el stream token a token.


    Paso 2: El modelo de datos

    Antes del componente, define la interfaz de mensaje. Simple:

    // src/app/chat/chat.types.ts
    export interface ChatMessage {
      role: 'user' | 'assistant';
      content: string;
    }
    

    Paso 3: El componente Angular v22 con Signals

    Aquí es donde la magia ocurre. No necesitas HttpClient con responseType: 'text' — eso no soporta streaming incremental. Necesitas fetch nativo con ReadableStream.

    // src/app/chat/chat.component.ts
    import {
      Component,
      signal,
      computed,
      ChangeDetectionStrategy,
    } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { ChatMessage } from './chat.types';
    
    @Component({
      selector: 'app-chat',
      standalone: true,
      imports: [FormsModule],
      changeDetection: ChangeDetectionStrategy.OnPush,
      templateUrl: './chat.component.html',
    })
    export class ChatComponent {
      messages = signal<ChatMessage[]>([]);
      userInput = signal('');
      isStreaming = signal(false);
    
      canSend = computed(
        () => this.userInput().trim().length > 0 && !this.isStreaming()
      );
    
      async sendMessage() {
        const content = this.userInput().trim();
        if (!content || this.isStreaming()) return;
    
        // Añadir mensaje del usuario
        this.messages.update((msgs) => [
          ...msgs,
          { role: 'user', content },
        ]);
        this.userInput.set('');
        this.isStreaming.set(true);
    
        // Capturar mensajes ANTES del placeholder — la API rechaza content vacío como último mensaje
        const messagesToSend = this.messages();
    
        // Placeholder para la respuesta del asistente
        this.messages.update((msgs) => [
          ...msgs,
          { role: 'assistant', content: '' },
        ]);
    
        try {
          const response = await fetch('http://localhost:3000/api/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ messages: messagesToSend }),
          });
    
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          if (!response.body) throw new Error('No stream body');
    
          const reader = response.body.getReader();
          const decoder = new TextDecoder();
    
          while (true) {
            const { done, value } = await reader.read();
            if (done) break;
    
            const chunk = decoder.decode(value, { stream: true });
    
            // Actualiza el último mensaje (el del asistente) acumulando el chunk
            this.messages.update((msgs) => {
              const updated = [...msgs];
              const last = updated[updated.length - 1];
              updated[updated.length - 1] = {
                ...last,
                content: last.content + chunk,
              };
              return updated;
            });
          }
        } catch (error) {
          console.error('Error en streaming:', error);
          this.messages.update((msgs) => {
            const updated = [...msgs];
            updated[updated.length - 1] = {
              role: 'assistant',
              content: 'Error al conectar con el servidor. Comprueba que el backend está corriendo.',
            };
            return updated;
          });
        } finally {
          this.isStreaming.set(false);
        }
      }
    
      handleEnter(event: KeyboardEvent) {
        if (event.key === 'Enter' && !event.shiftKey) {
          event.preventDefault();
          this.sendMessage();
        }
      }
    }
    

    Tres decisiones clave en este componente:

    messages = signal<ChatMessage[]>([]) — todo el historial de la conversación vive en un signal. Cada vez que llega un chunk, actualizamos el último mensaje del array con update(). Angular detecta el cambio y re-renderiza solo ese elemento.

    ChangeDetectionStrategy.OnPush — esencial para este patrón. Sin esto, Angular ejecutaría la detección de cambios en cada tick mientras el stream está activo. Con OnPush + Signals, Angular solo actualiza cuando el signal cambia — que es exactamente cuando llega un chunk nuevo.

    fetch nativo en lugar de HttpClientHttpClient es poderoso para peticiones normales, pero para streaming necesitas acceso al ReadableStream crudo del Response. fetch te da eso directamente con response.body.getReader().


    Paso 4: El template con el nuevo control flow

    El template aprovecha el control flow de Angular v17+ (@for, @if) y lee los signals directamente — sin async pipe, sin | async, sin subscripciones.

    <!-- src/app/chat/chat.component.html -->
    <div class="chat-container">
      <div class="messages-area">
        @if (messages().length === 0) {
          <p class="empty-state">Escribe un mensaje para empezar.</p>
        }
    
        @for (msg of messages(); track $index) {
          <div class="message" [class]="msg.role">
            <span class="role-label">
              {{ msg.role === 'user' ? 'Tú' : 'Asistente' }}
            </span>
            <p class="message-content">{{ msg.content }}</p>
    
            @if (msg.role === 'assistant' && $last && isStreaming()) {
              <span class="cursor-blink">|</span>
            }
          </div>
        }
      </div>
    
      <div class="input-area">
        <textarea
          [value]="userInput()"
          (input)="userInput.set($any($event.target).value)"
          (keydown)="handleEnter($event)"
          placeholder="Escribe tu mensaje... (Enter para enviar)"
          rows="3"
          [disabled]="isStreaming()"
        ></textarea>
    
        <button
          (click)="sendMessage()"
          [disabled]="!canSend()"
        >
          @if (isStreaming()) {
            Generando...
          } @else {
            Enviar
          }
        </button>
      </div>
    </div>
    

    El cursor parpadeante | aparece solo en el último mensaje del asistente mientras isStreaming() es true. Es un detalle pequeño que hace que la experiencia se sienta viva.


    Paso 5: Estilos mínimos (opcional)

    /* src/app/chat/chat.component.css */
    .chat-container {
      display: flex;
      flex-direction: column;
      height: 100vh;
      max-width: 800px;
      margin: 0 auto;
      padding: 1rem;
      gap: 1rem;
    }
    
    .messages-area {
      flex: 1;
      overflow-y: auto;
      display: flex;
      flex-direction: column;
      gap: 1rem;
      padding: 1rem;
      border: 1px solid #e5e7eb;
      border-radius: 0.5rem;
    }
    
    .message {
      padding: 0.75rem 1rem;
      border-radius: 0.5rem;
      max-width: 80%;
    }
    
    .message.user {
      background: #e90464;
      color: white;
      align-self: flex-end;
    }
    
    .message.assistant {
      background: #f3f4f6;
      color: #111827;
      align-self: flex-start;
    }
    
    .role-label {
      font-size: 0.75rem;
      font-weight: 600;
      opacity: 0.7;
      display: block;
      margin-bottom: 0.25rem;
    }
    
    .cursor-blink {
      animation: blink 1s step-end infinite;
    }
    
    @keyframes blink {
      50% { opacity: 0; }
    }
    
    .input-area {
      display: flex;
      gap: 0.5rem;
    }
    
    textarea {
      flex: 1;
      padding: 0.75rem;
      border: 1px solid #d1d5db;
      border-radius: 0.5rem;
      resize: none;
      font-family: inherit;
    }
    
    button {
      padding: 0.75rem 1.5rem;
      background: #e90464;
      color: white;
      border: none;
      border-radius: 0.5rem;
      cursor: pointer;
      font-weight: 600;
      align-self: flex-end;
    }
    
    button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
    

    El resultado

    Arranca los dos procesos:

    # Terminal 1: backend
    bun run server/chat.ts
    
    # Terminal 2: Angular
    ng serve
    

    Abre http://localhost:4200. Escribe cualquier pregunta técnica. Las palabras aparecen token a token mientras Claude las genera. El botón muestra "Generando…" y el cursor parpadea al final del último mensaje.

    Eso es streaming real, en Angular v22, con Signals, en menos de 20 minutos.


    Por qué este patrón funciona bien en producción

    Si quieres entender cómo se conectan estos patrones con el desarrollo de productos completos con IA, el post sobre cómo crear productos con IA para vender muestra el panorama completo.

    Lo que tienes aquí no es un prototipo. Es un patrón que escala:

    El estado es predecible. Todo vive en messages = signal<ChatMessage[]>([]). No hay subscripciones dispersas, no hay Subject de BehaviorSubject, no hay que recordar hacer unsubscribe. El signal se actualiza, Angular re-renderiza lo necesario, punto.

    El backend es stateless. Cada petición envía el historial completo de mensajes. Así funciona la API de Anthropic — no hay sesión en el servidor, lo que facilita el escalado horizontal.

    ChangeDetectionStrategy.OnPush es obligatorio aquí. Con Zone.js y la detección de cambios por defecto, Angular correría su ciclo de detección constantemente mientras el stream está activo. Con OnPush + Signals, solo actualiza cuando el signal cambia.

    Si quieres llevar esto más allá — añadir herramientas (tool calls), mantener sesiones con localStorage, o integrar el chat dentro de una app Angular más grande con routing y autenticación — el patrón es el mismo. Cambias el modelo en el servidor, añades tools a streamText, y el componente no necesita modificarse.

    Si ya tienes experiencia con Angular y quieres dominar Signals, componentes standalone y el control flow moderno que hemos usado aquí, en el Curso Angular Moderno lo cubrimos desde la arquitectura hasta producción — incluyendo patrones de integración con APIs externas como esta.

    Y si quieres ir más allá del chat básico y construir agentes reales con Claude — con herramientas, contexto persistente, y pipelines de desarrollo AI-first — eso es exactamente lo que enseñamos en Construye con IA: de la idea al producto con Claude Code.


    FAQ

    ¿Necesito Angular Universal (SSR) para que esto funcione?

    No. El streaming ocurre entre el cliente Angular (browser) y el servidor Bun que creamos. Angular SSR es irrelevante para este patrón — el componente de chat vive completamente en el cliente. Si tienes SSR activado, asegúrate de que el componente de chat solo se renderiza en el browser con isPlatformBrowser o usando @defer.

    ¿Puedo usar el mismo enfoque con OpenAI o Google Gemini en lugar de Anthropic?

    Sí. Cambia @ai-sdk/anthropic por @ai-sdk/openai o @ai-sdk/google, y sustituye anthropic('claude-sonnet-4-6') por openai('gpt-4o') o google('gemini-2.5-pro'). El resto del código — el componente Angular, el consumo del stream, los Signals — no cambia. Esa es una de las ventajas del Vercel AI SDK: abstrae el proveedor.

    ¿Qué pasa si el usuario envía el siguiente mensaje mientras el anterior aún está en streaming?

    El botón está deshabilitado mientras isStreaming() es true gracias al computed canSend. El usuario no puede enviar otro mensaje hasta que el stream termine. Si quieres cancelar el stream activo al recibir un nuevo mensaje, puedes guardar el reader como propiedad del componente y llamar a reader.cancel() antes de iniciar la nueva petición.

    ¿Cómo manejo el historial para conversaciones largas?

    La API de Anthropic tiene un límite de tokens por request. Para conversaciones largas, lo más simple es limitar el historial que envías al servidor — por ejemplo, los últimos 20 mensajes. En producción, lo correcto es implementar una ventana deslizante o resumir el historial antiguo con un llamada previa al modelo. Por ahora, con this.messages().slice(-20) en el body del fetch tienes un control básico suficiente para empezar.

    ¿Puedo usar HttpClient en lugar de fetch nativo?

    HttpClient con responseType: 'text' recibe el texto completo cuando la conexión cierra — no es streaming incremental. Para streaming real necesitas acceso al ReadableStream crudo de la Response, que solo fetch te proporciona directamente. Podrías implementar un interceptor custom o un HttpBackend alternativo, pero la complejidad no vale la pena. fetch nativo es la solución correcta aquí.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Next.js 16.3 Instant Navigations: cero esperas al navegar

    Next.js 16.3 Instant Navigations: cero esperas al navegar

    Llevaba semanas con una queja recurrente de un cliente. Su app en Next.js con App Router se sentía lenta. No el server, no la base de datos — las navegaciones. Hacías clic en un enlace y durante un segundo entero no pasaba nada. Literalmente nada. Next.js 16.3 Instant Navigations es la respuesta directa a ese problema.

    En un modelo server-driven, cada navegación implica un roundtrip de red. El cliente espera, el servidor procesa, responde, aparece la página. En una SPA ese segundo no existe — el cliente muestra una shell inmediata mientras los datos llegan. Next.js había apostado por el servidor, pero el coste en percepción de velocidad era real.

    Nota de versión: Next.js 16.3 está actualmente en preview (instalable con npm install next@preview). Las APIs que describo aquí son las publicadas el 25 de junio de 2026 en el blog oficial de Next.js. Pueden cambiar antes del release estable.


    El problema que 16.3 viene a resolver

    En Next.js clásico con Server Components, el flujo de navegación era este:

    1. El usuario hace clic en un enlace.
    2. El navegador no hace nada visible.
    3. El servidor procesa la ruta, genera el HTML, responde.
    4. La página aparece.

    Para apps orientadas a contenido — un blog, un periódico — esto funciona. Para dashboards, herramientas internas, apps tipo SaaS, ese segundo de nada destruye la experiencia.

    Las SPAs resuelven esto de otra forma: descargan el código de cada ruta de antemano y muestran una shell inmediata mientras los datos llegan. Sensación instantánea. Next.js tenía el prefetching, pero lo hacía a nivel de link individual, lo que generaba decenas de peticiones al servidor cada vez que el usuario hacía scroll por una lista de enlaces.

    16.3 cambia los dos flancos del problema.


    Cómo funciona Instant Navigations

    Paso 1: habilitar Cache Components

    Todo empieza con un flag en next.config.ts:

    // next.config.ts
    import type { NextConfig } from 'next';
    
    const nextConfig: NextConfig = {
      cacheComponents: true,
    };
    
    export default nextConfig;
    

    Este flag activa el modelo de Cache Components — el nuevo paradigma de Next.js donde el caching es explícito con 'use cache' en lugar de implícito y confuso como en versiones anteriores. Con él habilitado, Next.js puede generar un "shell" para cada ruta: la parte de la UI que puede renderizarse sin esperar al servidor.

    Paso 2: elegir el modo de cada ruta — Stream, Cache o Block

    Con Cache Components activo, cuando una ruta hace await a datos del servidor, Next.js en desarrollo te muestra un panel llamado Instant Insights. Este panel detecta qué rutas están bloqueando la navegación y te da tres opciones:

    Stream con <Suspense>

    La ruta muestra inmediatamente una shell con estados de carga, y los datos se van incluyendo por streaming conforme llegan:

    // app/products/[id]/page.tsx
    import { Suspense } from 'react';
    import { ProductDetail } from './product-detail';
    import { ProductSkeleton } from './product-skeleton';
    
    export default async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
      const { id } = await params;
      return (
        <div>
          <h1>Producto</h1>
          <Suspense fallback={<ProductSkeleton />}>
            <ProductDetail id={id} />
          </Suspense>
        </div>
      );
    }
    

    La navegación es inmediata. El usuario ve la shell con el skeleton. Los datos llegan después. Sensación de SPA.

    Cache con 'use cache'

    Si la ruta depende de datos que se pueden cachear, marcas la función con 'use cache' y Next.js sirve el resultado cacheado de forma instantánea en navegaciones posteriores:

    // app/dashboard/analytics/page.tsx
    import { unstable_cacheLife as cacheLife } from 'next/cache';
    import { Suspense } from 'react';
    
    async function AnalyticsSection() {
      'use cache';
      cacheLife('minutes'); // TTL de caché explícito
      const data = await fetchAnalytics();
      return <Chart data={data} />;
    }
    
    export default function AnalyticsPage() {
      return (
        <Suspense fallback={<AnalyticsSkeleton />}>
          <AnalyticsSection />
        </Suspense>
      );
    }
    

    El usuario ve el contenido cacheado de forma inmediata. Si el cache está fresco, la experiencia es idéntica a una SPA.

    Block: cuando quieres que la navegación espere al servidor

    Hay casos donde no quieres mostrar una shell. Un blog no debería mostrar un spinner donde va el artículo — o muestras el artículo o no navegas. Para esos casos, exportas instant = false:

    // app/blog/[slug]/page.tsx
    export const instant = false; // Esta ruta bloquea hasta tener respuesta del servidor
    
    export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
      const { slug } = await params;
      const post = await getPost(slug);
      return <Article post={post} />;
    }
    

    Next.js deja de reportar esta ruta como problema de rendimiento. Has decidido conscientemente que prefieres la espera a mostrar una UI incompleta. La diferencia es que ahora es una decisión explícita, no un comportamiento por defecto que no entiendes.


    Partial Prefetching: prefetchear smarter, no harder

    El segundo gran cambio es cómo Next.js hace prefetching.

    En 16.2, si tenías una lista de veinte enlaces a /chat/[id], Next.js enviaba veinte peticiones de prefetch al servidor — una por link visible en el viewport. Ineficiente y costoso.

    En 16.3, con Partial Prefetching habilitado, Next.js prefetchea un shell por ruta, no por link. Veinte links a /chat/[id] generan exactamente una petición: la del shell de /chat/[id]. Ese shell se cachea en el cliente durante toda la sesión.

    Para habilitarlo:

    // next.config.ts
    import type { NextConfig } from 'next';
    
    const nextConfig: NextConfig = {
      cacheComponents: true,
      partialPrefetching: true,
    };
    
    export default nextConfig;
    

    Prefetching por link cuando necesitas más

    El Partial Prefetching es conservador por diseño — solo prefetchea el shell. Si quieres que un link concreto prefetchee también contenido específico, añades prefetch={true} al componente <Link>:

    // Una lista donde quieres que el header del chat se vea instantáneamente
    export function ChatList({ chats }: { chats: Chat[] }) {
      return (
        <ul>
          {chats.map(chat => (
            <li key={chat.id}>
              {/* Prefetch completo para este link */}
              <Link href={`/chat/${chat.id}`} prefetch={true}>
                {chat.title}
              </Link>
            </li>
          ))}
        </ul>
      );
    }
    

    Y si quieres que el prefetch incluya contenido dinámico de request-time (no solo build-time), lo permites explícitamente en la ruta:

    // app/chat/[id]/page.tsx
    export const prefetch = 'allow-runtime';
    

    La ventaja respecto al comportamiento anterior: ya no es todo o nada. Tienes granularidad real.


    Navigation Inspector: ve el shell antes de que el usuario llegue

    El Navigation Inspector es una herramienta de las Next.js DevTools que pausa cualquier navegación en el momento exacto del shell — antes de que lleguen los datos del servidor — mostrando visualmente qué partes de la ruta son instantáneas y cuáles requieren una petición de red.

    En la práctica: haces clic en un enlace, el inspector lo detiene en el shell, ves el mapa completo de tu ruta. Cuando haces clic en "Resume", la navegación completa. Especialmente útil para identificar componentes que bloquean la navegación porque hacen await sin <Suspense> ni 'use cache'.


    Testing: el helper instant() para Playwright

    Para que las mejoras de rendimiento no retrocedan con refactorizaciones futuras, Next.js 16.3 incluye un test helper para Playwright:

    // tests/navigation.spec.ts
    import { expect, test } from '@playwright/test';
    import { instant } from '@next/playwright';
    
    test('el header del producto aparece sin esperar al servidor', async ({ page }) => {
      await page.goto('/products/shoes');
    
      // Todo lo que esté dentro de este bloque debe ser visible SIN red
      await instant(page, async () => {
        await page.click('a[href="/products/hats"]');
        await expect(page.locator('h1')).toContainText('Baseball Cap');
        await expect(page.getByText('Checking inventory...')).toBeVisible();
      });
    
      // Esto sí puede esperar al servidor
      await expect(page.getByText('12 in stock')).toBeVisible();
    });
    

    instant() es el equivalente a un test de performance integrado en tu suite de e2e. Si un refactor convierte una ruta Stream en una ruta bloqueante, el test falla. Sin sorpresas en producción.

    Si ya tienes tests de Angular y quieres aplicar la misma mentalidad a tus proyectos — testear comportamiento, no implementación — el curso de Testing en Angular te da esa base de forma sólida con Jest y Testing Library.


    Comparativa: antes vs. después

    Aspecto Next.js 16.2 Next.js 16.3
    Comportamiento por defecto Bloquea hasta respuesta del servidor Stream o Cache para navegación inmediata
    Prefetching 1 petición por link en viewport 1 shell por ruta, reutilizado entre links
    Control por ruta No hay export const instant = false para rutas bloqueantes
    Herramienta de diagnóstico Ninguna Instant Insights + Navigation Inspector
    Testing de regresiones Manual instant() helper para Playwright
    Configuración Implícita y confusa Explícita con cacheComponents y partialPrefetching

    Cómo empezar hoy mismo

    Para probar Instant Navigations en un proyecto existente:

    1. Instala el preview:

      npm install next@preview
      
    2. Habilita los flags en next.config.ts:

      const nextConfig: NextConfig = {
        cacheComponents: true,
        partialPrefetching: true,
      };
      
    3. Arranca el servidor de desarrollo. Verás el panel Instant Insights con las rutas que están bloqueando la navegación.

    4. Identifica, decide y verifica. Para cada ruta bloqueante, elige Stream, Cache o Block. El Navigation Inspector confirma que el shell funciona antes de ir a producción.

    El equipo de Vercel lo validó en v0 — su propia app — antes del release. Los tiempos de navegación bajaron significativamente en las rutas que adoptaron el nuevo modelo.

    Si quieres ver cómo se integra este tipo de arquitectura con IA y streaming en tiempo real, en Dominicode Labs estamos construyendo proyectos que combinan Next.js con streaming de LLMs — exactamente el tipo de apps donde Instant Navigations marca la diferencia más visible. Para entender la Claude API con TypeScript antes de integrarla, este crash course es el punto de partida.


    Casos de uso donde esto cambia más

    Dashboards con datos en tiempo real. Cada cambio de sección era un segundo de espera. Con Stream + Suspense, el layout del dashboard aparece inmediatamente y los datos llegan después.

    Apps de chat o mensajería. Con Partial Prefetching, navegar entre conversaciones — aunque sean decenas — genera una sola petición de prefetch por ruta, no una por cada enlace visible.

    E-commerce. Las páginas de producto pueden mostrar la estructura (imagen placeholder, nombre, botón "Añadir al carrito") de forma instantánea mientras el inventario y el precio se cargan.

    Herramientas internas con muchas secciones. El menú lateral con 30 links ya no genera 30 peticiones de prefetch al cargar la página.

    Si trabajas con Astro para partes estáticas de tu sitio y Next.js para las dinámicas, el análisis de Astro v7 te ayuda a decidir qué encaja en cada capa.


    FAQ

    ¿Instant Navigations funciona con el Pages Router o solo con App Router?

    Solo con App Router. Cache Components y el modelo de shells requieren Server Components, que no existen en Pages Router. Si aún tienes un proyecto en Pages Router, esta es una razón más para evaluar la migración.

    ¿cacheComponents: true cambia el comportamiento de caching de mis datos?

    Sí, de forma intencional. El nuevo modelo hace el caching explícito: nada se cachea por defecto a menos que uses 'use cache'. Si venías de fetch con opciones implícitas de cache, tendrás que revisar tu estrategia de datos. Es un cambio de paradigma, no solo un flag de navegación.

    ¿El Partial Prefetching incrementa el coste de servidor?

    Al contrario. En 16.2, con veinte links en pantalla tenías veinte peticiones de prefetch. En 16.3, con Partial Prefetching, tienes una petición por ruta distinta. En un escenario real con listas de items que apuntan al mismo route pattern, la reducción de peticiones puede ser del 90%.

    ¿Puedo usar <Link prefetch={true}> para todo y obtener el comportamiento anterior?

    Técnicamente sí, pero estarías ignorando el punto. El comportamiento anterior era ineficiente. <Link prefetch={true}> existe para casos específicos donde necesitas prefetchear más que el shell en un link concreto — no como reemplazo global del viejo modelo.

    ¿Cuándo sale el release estable de Next.js 16.3?

    No hay fecha oficial confirmada. El equipo indica que están resolviendo issues conocidos (algunos casos con Safari en Instant Insights, y rutas bloqueantes que no se reportan correctamente con Partial Prefetching activo). La recomendación es probar el preview en proyectos de desarrollo, no en producción.

    ¿Puedo escribir tests con instant() antes del release estable?

    Sí. El paquete @next/playwright ya incluye el helper y es seguro usarlo en tu suite de e2e. Si el release estable cambia el comportamiento, los tests te lo dirán antes de que llegue a producción.


    Next.js 16.3 no reinventa el framework. Lo que hace es cerrar la brecha más molesta que tenían los Server Components: la sensación de lentitud al navegar. Stream, Cache y Block son tres palabras, pero detrás hay un modelo de pensamiento claro sobre qué parte de tu UI puede ser instantánea y cuál no.

    La clave no está en activar los flags y esperar magia. Está en recorrer tus rutas con el Navigation Inspector, entender qué está bloqueando, y tomar la decisión correcta para cada una.

    Si tu próximo proyecto combina Next.js con agentes de IA o herramientas de Claude Code, en el curso Construye con IA vemos exactamente cómo estructurar apps que necesitan streaming, caché inteligente y navegación fluida desde el primer día.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Claude Code Routines: automatiza agentes sin encender tu PC

    Claude Code Routines: automatiza agentes sin encender tu PC

    El viernes por la tarde cerré el portátil con 23 issues sin triagear en el repo, tres PRs esperando revisión de documentación y un changelog que nadie había actualizado en dos semanas.

    El lunes por la mañana, todo estaba hecho.

    No porque contraté a nadie. No porque dejé el ordenador encendido todo el fin de semana. Fue la primera vez que sentí que las Claude Code Routines no eran una feature más de Anthropic — eran la diferencia entre usar IA como herramienta y usarla como infraestructura.


    De herramienta a infraestructura: el salto que cambia todo

    Si ya usas Claude Code de forma interactiva, sabes lo que puede hacer. Le das contexto, le pides algo, revisa tu código, abre PRs. Pero todo depende de que tú estés sentado delante del teclado, iniciando cada conversación.

    Las Routines rompen esa dependencia.

    Una Routine es una configuración guardada de Claude Code: un prompt, uno o más repositorios y un conjunto de conectores (MCP), empaquetados una sola vez y ejecutados de forma automática. Lo que las hace distintas de cualquier script de bash con un cron job es que corren en la infraestructura cloud de Anthropic. Tu máquina puede estar apagada. Claude sigue trabajando.

    Están disponibles desde abril de 2026 en research preview para todos los planes de pago: Pro, Max, Team y Enterprise. Se crean desde claude.ai/code/routines — consulta la documentación oficial de Claude Code para ver los últimos límites y cambios.


    Los tres tipos de trigger

    Una Routine puede tener uno o varios triggers combinados. Esto es lo que hace que el modelo sea flexible de verdad.

    1. Schedule (cron)

    Ejecuta la Routine de forma recurrente: cada hora, diariamente, entre semana o cada semana. Si necesitas un intervalo personalizado — por ejemplo, cada dos horas o el primer día de cada mes — configuras el preset más cercano en la interfaz de claude.ai/code/routines.

    El intervalo mínimo es una hora. Expressions que corren con más frecuencia se rechazan.

    También existe el concepto de one-off run: disparas la Routine una sola vez en un timestamp futuro. Útil para recordatorios diferidos, limpiezas post-deploy o tareas que tienen que correr "cuando aterrice ese PR de upstream". Después de ejecutarse, la Routine se auto-deshabilita. Y un detalle importante: los one-off runs no cuentan contra el límite diario de Routines.

    2. GitHub event

    Dispara una sesión nueva automáticamente cuando ocurre un evento en un repositorio conectado. Los eventos soportados incluyen pull request (opened, closed, labeled, synchronized…) y release (created, published, edited…).

    Puedes añadir filtros para reducir exactamente cuándo se dispara: autor del PR, título, rama base, rama head, labels, si es draft o no, si está mergeado. Cada evento que pasa los filtros abre su propia sesión independiente — no hay reutilización de sesiones entre eventos.

    Para usar GitHub triggers hace falta instalar la Claude GitHub App en el repositorio. No basta con el acceso que configuras en /web-setup para clonar repos.

    3. Webhook (API trigger)

    Cada Routine con este trigger tiene un endpoint HTTP dedicado. Le haces POST con un bearer token y arranca una sesión nueva. El cuerpo de la request acepta un campo text opcional — puedes pasarle el cuerpo de una alerta, un stack trace o cualquier contexto que la Routine necesite para esa ejecución concreta.

    La respuesta devuelve el ID y la URL de la sesión creada, así puedes abrirla en el navegador para ver qué está haciendo Claude en tiempo real.

    curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEF.../fire \
      -H "Authorization: Bearer sk-ant-oat01-xxxxx" \
      -H "anthropic-beta: experimental-cc-routine-2026-04-01" \
      -H "anthropic-version: 2023-06-01" \
      -H "Content-Type: application/json" \
      -d '{"text": "Error crítico en producción: SEN-4521. Stack trace adjunto."}'
    

    Tres Routines que puedes activar esta semana

    Estos no son ejemplos de documentación. Son los casos de uso que más sentido tienen para un developer indie o un equipo pequeño.

    Triage de issues cada noche

    Un trigger de schedule que corre de lunes a viernes a las 23:00. El prompt le dice a Claude que lea todos los issues abiertos desde la última ejecución, aplique labels según el área de código referenciada, asigne propietario y publique un resumen en Slack. Llegas por la mañana con la cola de trabajo ya priorizada.

    Requiere: conector de GitHub + conector de Slack configurados como MCP connectors en tu cuenta de claude.ai.

    Code review automatizado en cada PR

    Un trigger de GitHub que reacciona a pull_request.opened con filtro is draft: false. El prompt aplica el checklist de revisión de tu equipo: seguridad, performance, style. Deja comentarios inline y un resumen para los revisores humanos. Los humanos se concentran en diseño y arquitectura — lo mecánico lo hace Claude.

    Este es el tipo de automatización que en equipos de 1-3 personas elimina el cuello de botella de revisión completamente.

    Changelog automático post-merge

    Un trigger de GitHub en pull_request.closed filtrado a is merged: true en la rama main. El prompt le pide a Claude que lea el diff del PR mergeado, extraiga el cambio relevante en lenguaje humano y lo añada al CHANGELOG.md en un PR nuevo. Sin nunca más tener que acordarte de documentar lo que acabas de subir a producción.


    Lo que paga el coste

    Las Routines consumen cuota de suscripción de la misma manera que una sesión interactiva. Además, hay un límite diario de runs por cuenta según el plan:

    • Pro: 5 runs diarios
    • Max: 15 runs diarios
    • Team / Enterprise: 25 runs diarios

    Si superas el límite o la cuota de suscripción, las ejecuciones siguientes se rechazan hasta que se resetea la ventana — salvo que tengas usage credits activados, en cuyo caso sigue corriendo en modo metered.

    Los GitHub triggers también tienen un cap por hora durante la research preview. Si un repositorio muy activo dispara demasiados eventos, los excedentes se descartan hasta que se resetea la ventana. Los límites actuales los ves en claude.ai/code/routines.

    El hecho de que sea research preview significa que los límites, la API y el comportamiento pueden cambiar. No construyas pipelines de producción críticos sobre esto todavía — pero sí es el momento perfecto para experimentar y entender cómo integrar esto en tu workflow.


    Routines vs. Managed Agents: no es lo mismo

    Anthropic también ha lanzado Claude Managed Agents con dos features que suenan parecidas pero son una capa distinta: Dreaming y Outcomes.

    La diferencia es importante para no confundirlos.

    Las Routines son un mecanismo de scheduling y ejecución. Definen cuándo y cómo corre una sesión de Claude Code. Son infraestructura de automatización.

    Dreaming es un proceso que revisa las sesiones pasadas de tus agentes y los memory stores, extrae patrones y perfecciona las memorias para que el agente mejore con el tiempo. Es un sistema de aprendizaje retrospectivo, no de ejecución de tareas.

    Outcomes es una feature de evaluación: defines un rubric de éxito y un evaluador separado (con su propio context window, para no contaminarse con el razonamiento del agente) revisa el output y le dice al agente qué corregir si no cumple el criterio. Es un loop de calidad, no de scheduling.

    Dicho de forma directa: las Routines responden a "¿cuándo y con qué trigger corre esto?". Managed Agents responde a "¿cómo mejora y cómo evalúa su propio output el agente?". Pueden usarse juntos, pero son capas con responsabilidades distintas.


    Un detalle que no está en la documentación oficial

    Cuando una Routine corre, lo hace de forma completamente autónoma. Sin permission mode, sin prompts de aprobación durante la ejecución. Claude puede ejecutar comandos de shell, usar skills del repositorio clonado y llamar a todos los conectores que hayas incluido.

    Esto es potente. Y también es la razón por la que el prompt de la Routine es el artefacto más importante del sistema. A diferencia de una sesión interactiva donde puedes corregir el rumbo, aquí el prompt tiene que ser autocontenido y explícito sobre qué hacer y qué aspecto tiene el éxito.

    Por defecto, Claude solo puede hacer push a ramas con prefijo claude/. Para permitirle escribir en ramas existentes o protegidas, tienes que habilitar explícitamente "Allow unrestricted branch pushes" en la configuración de la Routine. Una salvaguarda razonable.

    Las Routines pertenecen a tu cuenta individual de claude.ai. Los commits, los PRs y las acciones en conectores como Slack o Linear aparecen como tú — con tu identidad de GitHub, tu Slack, etc. Eso tiene implicaciones de auditoría que vale la pena tener en cuenta si trabajas en equipo.


    El shift real

    Llevo tiempo diciendo que el developer indie de 2026 puede operar con la capacidad de un equipo pequeño si usa bien las herramientas que tiene. Si llegas nuevo a Claude Code, el post sobre Effort, Models, Tools y Context te da el mapa completo antes de entrar en Routines. Y si quieres entender la capa de arquitectura detrás de los agentes, el post sobre agentic harness completa el cuadro. Las Routines son la prueba más concreta de eso que he visto hasta ahora.

    No es sobre chatear con IA. Es sobre delegar trabajo real a agentes que corren en la nube con tu identidad, contra tus repos, con tus herramientas. Y que lo hacen mientras tú duermes, estás en una reunión o simplemente tienes el portátil cerrado.

    Si llevas tiempo usando Claude Code de forma interactiva, las Routines son el siguiente paso natural. Si quieres un sistema para construir esto de forma ordenada — desde la idea hasta el producto sin caos — en el curso Construye con IA en Udemy cubrimos exactamente ese proceso: cómo estructurar el trabajo con Claude Code para que escale más allá de la sesión interactiva.

    Y si quieres ver cómo otros developers están implementando esto en proyectos reales, en Dominicode Labs estamos documentando los patrones que funcionan — incluyendo los prompts de Routines que uso en mi propio workflow.


    Preguntas frecuentes

    ¿Necesito tener mi servidor propio para usar Claude Code Routines?

    No. Las Routines corren directamente en la infraestructura cloud de Anthropic. No necesitas EC2, Railway, Fly.io ni ningún servidor propio. El único requisito es una suscripción de pago a Claude (Pro, Max, Team o Enterprise) con Claude Code on the web habilitado.

    ¿Cuál es la diferencia entre una Routine y un Desktop Scheduled Task?

    Los Desktop Scheduled Tasks corren en tu máquina local cuando el app de escritorio de Claude Code está abierto. Tienen acceso a tus archivos locales pero requieren que tu ordenador esté encendido. Las Routines corren en la nube de Anthropic independientemente de si tienes el ordenador encendido o el app abierto.

    ¿Puedo combinar varios tipos de trigger en la misma Routine?

    Sí. Una misma Routine puede tener triggers de schedule, de GitHub event y de API al mismo tiempo. Por ejemplo, una Routine de revisión de PRs puede correr de forma programada cada noche, dispararse también cuando se abre un PR nuevo en GitHub, y aceptar ejecuciones manuales vía webhook desde tu pipeline de CI/CD.

    ¿Qué pasa si una Routine falla o Claude no completa la tarea?

    El indicador de estado verde en el historial de runs solo significa que la sesión se inició y terminó sin errores de infraestructura — no que la tarea se completó con éxito. Para saber qué hizo Claude realmente tienes que abrir la sesión y revisar el transcript. Los errores de red, los conectores que faltan o los fallos a nivel de tarea aparecen en el transcript, no en el indicador de estado.

    ¿Las Routines tienen acceso a todos mis conectores MCP?

    Por defecto, cuando creas una Routine, incluye todos tus MCP connectors conectados en claude.ai. La recomendación de Anthropic es quitar los que no necesita la Routine específica para limitar el alcance de lo que Claude puede hacer durante la ejecución. Los MCP servers que hayas añadido localmente en el CLI con claude mcp add no están disponibles en Routines — tienes que añadirlos como connectors en claude.ai/customize/connectors.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • SDD 2026: por qué el spec define tu ventaja competitiva

    SDD 2026: por qué el spec define tu ventaja competitiva

    Un cliente me mandó su proyecto hace tres semanas. Llevaba dos meses usando Claude Code todos los días. El repositorio tenía 340 archivos. Tenía features. Tenía tests. El código compilaba.

    Y no tenía ni idea de qué hacía el sistema.

    Me preguntó: “¿Por qué cada vez que añado algo nuevo, rompo tres cosas que ya funcionaban?” La respuesta era visible desde el primer git log: llevaba dos meses pidiéndole a la IA que generara código sin decirle nunca qué estaba construyendo realmente. Cada prompt era una instrucción táctica. Nunca había una visión. Nunca un mapa.

    Eso es Spec-Driven Development (SDD) al revés. Y en 2026, con agentes que pueden escribir mil líneas en minutos, la diferencia entre los dos modos es la diferencia entre un producto y un desastre con tests.


    La IA no necesita que seas más rápido. Necesita que seas más claro.

    La narrativa que se vende sobre el desarrollo con IA es esta: “ahora puedes construir el doble de rápido”. Es verdad. El problema es que construir el doble de rápido sin dirección no te lleva antes a destino — te lleva el doble de lejos en la dirección equivocada.

    Los agentes de IA son ejecutores extraordinariamente potentes con cero criterio arquitectónico propio. Claude Code, GitHub Copilot, Cursor, cualquiera — siguen instrucciones. Si las instrucciones son vagas, el output es coherente localmente e incoherente globalmente. Cada archivo tiene sentido en sí mismo. El sistema entero no tiene sentido como conjunto.

    El spec no es documentación. No es burocracia. Es la única forma de darle a un agente de IA el contexto suficiente para que sus decisiones locales sean coherentes con la visión global.

    Sin spec, el agente está adivinando constantemente. Y adivina bien, frase a frase. Pero adivinar bien frase a frase no produce un párrafo con sentido — produce contenido que parece correcto y no lleva a ningún lado.


    Qué es SDD y por qué no es lo que crees

    Spec-Driven Development no es escribir documentación antes de programar. Eso es lo que la mayoría imagina y por lo que lo descartan: “ya tengo suficiente trabajo sin añadir Word docs al proceso”.

    SDD es una metodología de tres artefactos que define qué construyes, cómo lo construyes y en qué orden lo construyes — antes de que un solo agente escriba una sola línea de código.

    Los tres artefactos son:

    spec.md — el qué. La especificación estructurada del sistema. Tiene seis secciones fijas: Visión, Usuarios, Funcionalidades, Flujos, Arquitectura, NFRs. En total, tres o cuatro páginas que responden a la pregunta que ningún agente puede responder por ti: qué problema resuelves exactamente, para quién, y qué significa “hecho” en este proyecto.

    plan.md — el cómo. El plan técnico por fases. No divide el trabajo en tareas sueltas — divide el trabajo en capas que tienen sentido en secuencia. Primero el dominio, después la infraestructura, después la UI. No al revés. El plan.md es el documento que evita que empieces por la pantalla de login cuando el sistema de autenticación aún no existe.

    tasks.md — el orden. La lista de tareas ordenada para TDD. Cada tarea define qué test escribes primero y qué código lo hace pasar. El tasks.md convierte el plan en commits atómicos verificables. Cuando un agente ejecuta una tarea del tasks.md, el resultado es predecible: un test verde y un incremento de funcionalidad real.

    Estos tres documentos no tardan tres días en escribirse. Con el skill /dominicode-sdd-spec-creator en Claude Code (disponible para miembros de Dominicode Labs), la estructura completa se genera en minutos a partir de una descripción del proyecto. Lo que tarda tiempo es pensar — y ese tiempo es exactamente el que te ahorra deuda técnica después.


    Antes vs después: el mismo proyecto, dos formas de empezar

    Hace unos meses construí un sistema de gestión de contenido para automatizar la publicación en múltiples canales. El proyecto tenía integraciones con tres APIs externas, lógica de colas, transformaciones de formato y un dashboard de seguimiento.

    Sin SDD (como lo hubiera hecho en 2022): Habría abierto el editor, creado una carpeta src/, y empezado por la parte que más me apetecía — probablemente el dashboard. A las dos semanas tendría un dashboard bonito conectado a datos hardcodeados, una integración con una API que funcionaba en happy path, y ninguna certeza de cómo conectar las piezas. Cada decisión técnica habría sido local, sin visión del sistema completo.

    Con SDD: Antes de escribir código, escribí el spec.md. La sección de Flujos me forzó a pensar en qué pasa cuando una API falla en mitad de una publicación — algo que no habría considerado hasta toparme con el bug en producción. La sección de NFRs me hizo definir qué latencia máxima era aceptable para el sistema de colas. La sección de Arquitectura me hizo elegir entre evento-driven y polling antes de escribir nada — no a mitad del proyecto cuando cambiar de dirección cuesta semanas.

    El spec.md tardó dos horas. El plan.md, una hora más. El tasks.md, otra hora.

    Cuatro horas de especificación que eliminaron tres semanas de refactoring posterior.

    Cuando empecé a usar Claude Code en el proyecto, el agente tenía el spec.md en el contexto. Cada decisión técnica que tomaba era coherente con la arquitectura definida. No porque el LLM sea mágicamente más inteligente con un documento — sino porque el documento le daba información que de otra forma no tenía.


    El spec como brújula del agente

    Este es el cambio de mentalidad que más cuesta hacer: el spec no es para ti. Es para el agente.

    Cuando llevas quince años programando, tu cabeza tiene el contexto del proyecto. Sabes por qué elegiste ese patrón. Sabes qué módulo toca qué. Sabes los trade-offs que hiciste en la semana dos. Ese contexto vive en tu cabeza y lo das por supuesto.

    El agente no tiene nada de eso. Sin contexto explícito, cada sesión empieza desde cero. Cada prompt es una petición descontextualizada si no le das el marco. Sin spec, el agente responde a lo que le preguntas — no a lo que necesitas construir.

    Con el spec.md en contexto, el agente puede hacer preguntas que de otra forma no haría: “esta funcionalidad que me pides entra en conflicto con el flujo de usuario número tres que está en el spec — ¿quieres cambiar el flujo o ajustar la funcionalidad?”. Esa pregunta vale más que mil líneas de código generado sin contexto.

    Esta es exactamente la lógica detrás del libro Spec-Driven Development — no es un manual de documentación, es una metodología diseñada para que el agente tenga suficiente contexto para tomar decisiones correctas sin que tú estés micromanageando cada prompt.


    Por qué el spec te protege del vibe coding

    El vibe coding no es programar con IA. Es programar con IA sin criterio. Hay developers que publican proyectos enteros generados en un fin de semana. Impresionante en superficie. Inutilizable en producción.

    El problema del vibe coding no es la velocidad — es la ausencia de coherencia acumulada. Cada prompt genera código coherente con el prompt anterior, pero nadie garantiza que el sistema resultante sea coherente con la intención original. A las cuatro horas de vibe coding, el proyecto tiene forma de algo pero no tiene diseño. Tiene features pero no tiene arquitectura.

    Lo que se acumula en silencio no es código malo — es deuda técnica agéntica. El tipo de deuda que no se ve en los tests porque los tests también los generó el agente sin un contrato claro de qué probar. El tipo de deuda que explota cuando intentas añadir la feature número veinte sobre una base que asumió implícitamente cosas que nunca se definieron.

    Para entender por qué la arquitectura de tus agentes necesita un spec detrás, te recomiendo el post sobre agentic harness: por qué la spec y la arquitectura no bastan.

    SDD es el antídoto no porque ralentice el desarrollo. Lo acelera — pero acelera el desarrollo en la dirección correcta. La spec es el contrato que el agente respeta en cada iteración. El plan es la secuencia que evita que construyas la décima planta antes de los cimientos. El tasks.md son los commits que puedes revisar, aprobar y revertir si algo no cuadra.

    Con SDD, el vibe coding se convierte en agile coding con contexto — velocidad de agente, criterio de arquitecto.


    Cómo empezar con SDD en Claude Code hoy

    Si tienes Claude Code y quieres aplicar SDD en tu próximo proyecto, el proceso es directo:

    1. Describe tu proyecto en lenguaje natural — qué construyes, para quién, qué problema resuelve.
    2. Ejecuta el skill /dominicode-sdd-creator — genera spec.md, plan.md y tasks.md en pocos minutos (disponible en Dominicode Labs).
    3. Revisa el spec antes de tocar código — es el momento de pensar, no después.
    4. Añade el spec.md al contexto de Claude Code con @spec.md al inicio de cada sesión de desarrollo — la documentación oficial de Claude Code explica cómo gestionar el contexto entre sesiones.
    5. Trabaja el tasks.md en secuencia — un task, un test, un commit.

    El skill no reemplaza tu pensamiento. Te obliga a pensar antes de que sea costoso cambiar de dirección.

    El post sobre SDD Creator, la herramienta CLI muestra exactamente cómo se genera la estructura automáticamente.

    Si quieres ver cómo se aplica esto en un proyecto real de principio a fin — desde la spec inicial hasta el deploy — es exactamente lo que trabajamos en el curso Construye con IA: no tutoriales sueltos de herramientas, sino el proceso completo de construir un producto con IA de forma que funcione en producción.


    El spec como ventaja competitiva real

    Hay algo que nadie dice sobre SDD en 2026 y que merece decirse.

    En un mundo donde cualquier developer puede generar código a gran velocidad con IA, la diferencia competitiva no está en quién genera más rápido. Está en quién sabe exactamente qué construir y por qué.

    El spec es donde vive esa ventaja. No en el prompt. No en la elección del modelo. En la claridad con la que defines el problema antes de que empiece la ejecución.

    Los developers que entienden esto ya no compiten con los que “usan IA para programar más rápido”. Son una categoría diferente: developers que combinan criterio técnico con capacidad de ejecución agéntica. El spec es la expresión concreta de ese criterio.

    Dentro de doce meses, los equipos que hayan integrado SDD en su workflow tendrán bases de código mantenibles, documentación generada como efecto colateral del proceso, y la capacidad de incorporar nuevos agentes o nuevos developers sin que el proyecto colapse. Los que sigan con vibe coding habrán reescrito el proyecto tres veces.


    FAQ

    ¿SDD no es simplemente documentación con otro nombre?

    No. La documentación describe lo que existe. El spec define lo que va a existir — antes de que exista. La diferencia no es semántica: la documentación se escribe después y siempre está desactualizada. El spec se escribe antes y guía la implementación. Si el spec y el código divergen durante el desarrollo, es señal de que hay una decisión técnica que tomar conscientemente — no de que el documento esté equivocado.

    ¿Cuánto tiempo tarda escribir el spec de un proyecto real?

    Depende del proyecto. Para un MVP de funcionalidad acotada, entre dos y cuatro horas. Para un sistema con múltiples integraciones y flujos complejos, un día. El punto de referencia útil: si el spec tarda más de un día en escribirse, es señal de que el proyecto no está suficientemente definido para empezar a construirlo — y ese es el momento exacto en que el spec te está salvando, no ralentizando.

    ¿Se puede aplicar SDD a proyectos que ya existen?

    Sí, pero el proceso es diferente. En proyectos existentes, el spec se usa para nuevas features o para refactorizaciones significativas. El ejercicio de escribir el spec de un módulo existente es también un audit implícito: si no puedes escribir el spec del módulo, es porque el módulo no tiene diseño coherente. El spec revela la deuda técnica que el código oculta.

    ¿SDD funciona con cualquier agente de IA o solo con Claude Code?

    La metodología es agnóstica al agente. Spec.md, plan.md y tasks.md son documentos markdown que cualquier LLM puede usar como contexto. El skill /dominicode-sdd-spec-creator está diseñado para Claude Code y disponible en Dominicode Labs, pero los artefactos que genera son compatibles con cualquier entorno. Lo importante no es la herramienta — es el hábito de definir antes de ejecutar.

    ¿Qué pasa cuando el spec cambia durante el desarrollo? ¿No es todo ese trabajo en vano?

    El spec cambia. Siempre cambia. Y eso es una funcionalidad, no un fallo. Cuando el spec cambia, tienes un documento que actualizar — y esa actualización fuerza una decisión consciente sobre el impacto del cambio en la arquitectura, los flujos y las tareas pendientes. Sin spec, el cambio ocurre de forma invisible: alguien pide algo diferente, el agente lo implementa, y nadie sabe qué asunciones antiguas quedan rotas. Con spec, el cambio es visible y gestionable.

    ¿Es SDD compatible con metodologías ágiles?

    Completamente. SDD no impone un ciclo de desarrollo — impone un hábito de especificación antes de ejecución. Dentro de un sprint de dos semanas, el spec de las features del sprint se escribe al inicio. El plan.md define el orden de implementación dentro del sprint. El tasks.md genera los tickets concretos. SDD convierte el backlog en artefactos ejecutables para agentes, no en listas de deseos sin criterio técnico.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Claude Code: Effort, Models, Tools y Context para developers

    Claude Code: Effort, Models, Tools y Context para developers

    La primera vez que abrí Claude Code, lo traté como un chat más inteligente. Le pegaba código, le pedía que lo arreglara, copiaba la respuesta. Funcionaba, pero lo estaba usando como una versión cara de Stack Overflow.

    Tardé tres semanas en entender que Claude Code no es un chatbot. Es un agente que ejecuta herramientas reales en tu sistema, que puede leer tu repositorio entero, que tiene niveles de razonamiento configurables y que toma decisiones en cadena sin que tú intervengas en cada paso.

    Cuando lo entendí así, cambió todo.

    Este post es lo que me hubiera gustado leer antes de empezar. No es un tutorial de instalación — asume que ya lo tienes corriendo. Es una explicación honesta de los cuatro conceptos que determinan si Claude Code trabaja para ti o contra ti: Effort, Models, Tools y Context.


    Effort — el nivel de razonamiento que decides gastar

    Cuando Claude Code procesa una tarea, no siempre piensa igual de profundo. Puedes configurar cuánto razonamiento aplica desde la UI de Claude Code o mediante la opción de esfuerzo en la configuración. Los niveles son cuatro: low, medium, high y max.

    Esto no es marketing. Es la diferencia entre gastar dos segundos y gastar dos minutos en una misma pregunta, con respuestas radicalmente distintas.

    Low — cuando la velocidad importa más que la precisión

    Con low, Claude Code responde rápido y sin profundizar demasiado. Es útil para tareas mecánicas y predecibles: renombrar variables, formatear código, generar boilerplate que ya tienes en mente pero no quieres teclear.

    Si le pides "añade un método toString() a esta clase", no necesita razonar sobre arquitectura. low es suficiente.

    Medium — el nivel por defecto para trabajo diario

    medium es lo que usas el 80% del tiempo. Hay razonamiento real, considera contexto, pero no entra en análisis profundo de consecuencias. Funciona bien para refactoring moderado, explicaciones técnicas, generación de tests unitarios para funciones simples.

    Es el equilibrio entre velocidad y calidad que necesitas en un flujo de trabajo normal.

    High — cuando el error cuesta caro

    Aquí Claude Code empieza a razonar sobre consecuencias. Evalúa múltiples opciones antes de decidir, considera casos borde, analiza impacto en el resto del sistema.

    Úsalo cuando toques código crítico: un servicio de autenticación, la lógica de pagos, una migración de base de datos, un cambio arquitectural en el core de la aplicación. El tiempo extra que tarda se justifica con la reducción de errores no detectados.

    Max — análisis exhaustivo, sin atajos

    max activa el razonamiento más profundo disponible. Claude Code descompone el problema en partes, considera múltiples estrategias, evalúa trade-offs explícitamente.

    Esto no es para trabajo diario. Es para cuando necesitas que te ayude a diseñar la arquitectura de un módulo nuevo, cuando tienes un bug imposible de reproducir que llevas días persiguiendo, o cuando vas a tomar una decisión técnica con consecuencias a largo plazo.

    El coste es tiempo y tokens. La ganancia es profundidad real.

    Regla práctica: empieza con medium. Si la respuesta no llega al nivel que necesitas, sube un nivel. No uses max por defecto — no tiene sentido pagar el coste de razonamiento exhaustivo para añadir un campo en un formulario.


    Models — cuál elegir y por qué importa

    Claude Code tiene acceso a varios modelos bajo el capó. No todos son iguales en velocidad, coste ni capacidad. Elegir mal aquí es tirar dinero o tirar tiempo.

    A junio de 2026, los modelos disponibles en Claude Code son:

    Claude Haiku 4.5 — velocidad máxima, coste mínimo

    Haiku es el modelo pequeño. Responde en segundos, cuesta muy poco por token, y es más que suficiente para tareas de bajo peso cognitivo: completar líneas de código, responder preguntas de documentación, generar snippets concretos que ya tienes pensados.

    En un workflow agentic donde Claude Code ejecuta decenas de llamadas encadenadas (leer archivos, buscar patrones, escribir logs), Haiku hace el trabajo de las subtareas sin disparar el coste.

    Claude Sonnet 4.6 — el modelo de trabajo diario

    Sonnet es el punto dulce. Más capaz que Haiku en razonamiento y contexto largo, más rápido y barato que Opus, suficientemente potente para el 90% de las tareas de un developer.

    Refactoring complejo, generación de tests con lógica no trivial, debugging asistido, implementación de features completas — Sonnet lo maneja bien. Si no sabes cuál usar, empieza aquí.

    Claude Opus 4.8 — para problemas difíciles

    Opus es el modelo grande. Más lento, más caro, y considerablemente más capaz cuando el problema requiere razonamiento profundo, comprensión de contexto muy largo o análisis de consecuencias en sistemas complejos.

    No lo uses para tareas rutinarias. Sí lo uses cuando estés diseñando una arquitectura nueva, cuando el problema tiene múltiples dependencias que hay que razonar en paralelo, o cuando los outputs de Sonnet no son suficientemente precisos para tu caso.

    Claude Fable 5 — el modelo más potente

    Fable es el frontier model de Anthropic. Capacidades extendidas de razonamiento, mejor manejo de contexto muy largo y mayor precisión en tareas de alta complejidad. En Claude Code aparece como opción para las tareas más exigentes.

    Úsalo con criterio: el coste es significativamente mayor. Tiene sentido cuando diseñas sistemas críticos, cuando necesitas que el modelo razone sobre un codebase completo de miles de archivos, o cuando el nivel de precisión que necesitas no lo alcanza Opus.

    La decisión práctica: para trabajo diario usa Sonnet. Para subtareas rápidas y repetitivas dentro de un agente, Haiku. Para decisiones técnicas importantes o problemas difíciles, Opus o Fable. El modelo correcto no es el más potente — es el que resuelve el problema con el menor coste posible.


    Tools — las herramientas built-in que hacen a Claude Code un agente real

    Aquí está la diferencia fundamental entre Claude Code y un chatbot: Claude Code tiene herramientas que ejecuta de verdad en tu sistema. No simula leer archivos — los lee. No describe cómo haría una búsqueda — la hace.

    Estas son las herramientas principales y para qué sirve cada una:

    Herramienta Qué hace
    Read Lee el contenido de un archivo del filesystem. Claude ve exactamente lo que hay en el archivo, con números de línea.
    Edit Modifica un fragmento concreto de un archivo existente. Solo envía el diff, no reescribe todo el archivo.
    Write Crea un archivo nuevo o sobreescribe uno completo. Más costoso que Edit — úsalo solo cuando el cambio afecta a todo el archivo.
    Bash Ejecuta comandos de shell reales en tu sistema. Tests, builds, git, scripts, cualquier cosa que harías en terminal.
    Glob Busca archivos por patrón (**/*.ts, src/**/*.spec.ts). Útil para que Claude Code entienda la estructura del proyecto antes de actuar.
    Grep Busca contenido dentro de archivos por expresión regular. Para localizar dónde se usa una función, qué archivos importan un módulo, qué tests cubren una clase.
    WebSearch Hace búsquedas web reales. Útil cuando necesita documentación actualizada, información sobre versiones recientes o validar datos externos.
    WebFetch Descarga y procesa el contenido de una URL concreta. Para leer documentación oficial, specs de una API, changelog de una librería.
    Agent Lanza un subagente — una instancia paralela de Claude Code que ejecuta una subtarea de forma independiente. Arquitectura agentic en acción.
    TodoRead / TodoWrite Gestiona una lista de tareas interna de la sesión. Claude Code se auto-organiza las tareas que tiene pendientes en una tarea compleja.

    Lo que hace potente a este conjunto no es ninguna herramienta por sí sola — es la combinación. Claude Code lee la estructura del proyecto con Glob, localiza el código relevante con Grep, lo lee con Read, lo modifica con Edit, y ejecuta los tests con Bash. Todo en secuencia, sin que tú intervengas en cada paso.

    Este es el flujo que hace que una instrucción como "refactoriza el módulo de autenticación para que use el nuevo interceptor HTTP" produzca cambios reales en diez archivos distintos, con los tests pasando al final.

    La referencia completa de todas las herramientas y sus parámetros está en la documentación oficial de Claude Code.

    Si quieres ver cómo encajan estas herramientas con el resto del stack IA, en Stack IA agéntica en 2026: qué usar, qué ignorar y cuál elijo analizo exactamente eso.

    Si te interesa construir workflows agenticos más avanzados con Claude Code — desde la idea hasta un producto deployado — el curso Construye con IA: De la Idea al Producto con Claude y Specs cubre exactamente eso: cómo orquestar estas herramientas para que Claude Code trabaje con autonomía real.


    Context — cómo sabe Claude Code dónde está y qué importa

    El contexto es el factor más subestimado de Claude Code. Puedes tener el modelo correcto, el nivel de esfuerzo correcto y todas las herramientas disponibles — si Claude Code no entiende el contexto de tu proyecto, los outputs serán genéricos.

    @files y @folders — lo que le pones delante

    En la interfaz de Claude Code puedes mencionar archivos o carpetas con @. Cuando escribes @src/app/auth/auth.service.ts, Claude Code lee ese archivo y lo incluye directamente en el contexto de la conversación antes de procesar tu instrucción.

    Con @src/app/auth/ incluyes toda la carpeta. Claude Code procesa los archivos relevantes y construye una comprensión del módulo antes de actuar.

    Esto no es solo "adjuntar archivos". Es darle a Claude Code el mapa del territorio antes de pedirle que navegue.

    @url — documentación externa en tiempo real

    @url le permite a Claude Code leer el contenido de una URL y usarlo como contexto. Si necesitas que siga la documentación oficial de Angular v22 antes de modificar tu código de routing, puedes darle la URL del changelog y él la procesa.

    Esto elimina el problema clásico de los LLMs con conocimiento desactualizado. Si la librería sacó una versión nueva hace dos semanas, puedes darle la fuente actualizada directamente.

    CLAUDE.md — la memoria persistente del proyecto

    El archivo CLAUDE.md en la raíz de tu proyecto es la forma de darle a Claude Code instrucciones permanentes que se cargan en cada sesión.

    Aquí defines las convenciones del proyecto: cómo nombrar archivos, qué patrones arquitecturales seguís, qué comandos son los válidos, qué herramientas externas usáis, qué NO debe tocar sin confirmación explícita. Un CLAUDE.md bien escrito hace que Claude Code se comporte como un developer que conoce las reglas del equipo desde el primer día.

    No es opcional. Es la diferencia entre un agente que trabaja contigo y uno que trabaja en paralelo a ti sin coordinación.

    Memoria entre sesiones

    Por defecto, cada sesión de Claude Code empieza sin memoria de conversaciones anteriores. El contexto no persiste automáticamente.

    La forma correcta de manejar esto es el CLAUDE.md: las decisiones técnicas importantes, las convenciones acordadas, las restricciones del proyecto — todo lo que necesita persistir va ahí. No en el historial de conversación.

    Para proyectos más complejos, puedes estructurar archivos adicionales de contexto (specs, planes, documentos de arquitectura) y referenciarlos con @ al inicio de cada sesión. Es un flujo de trabajo, no una feature automática.

    En Dominicode Labs tenemos proyectos reales donde aplicamos exactamente esta estructura — con los archivos de contexto organizados para que Claude Code mantenga coherencia a lo largo de semanas de desarrollo.


    Cuatro hábitos para usar Claude Code como un agente real

    Claude Code no es difícil. Pero usarlo bien requiere entender que no es un chatbot avanzado — es un agente con herramientas reales, niveles de razonamiento configurables, múltiples modelos con características distintas, y un sistema de contexto que tú controlas.

    Elegir el modelo correcto para cada tarea, configurar el esfuerzo según lo que está en juego, dejar que las tools hagan el trabajo sin microgestionar cada paso, y mantener un CLAUDE.md que le dé continuidad al proyecto — esos cuatro hábitos son la diferencia entre usarlo como un buscador caro y usarlo como un colaborador técnico real.

    El siguiente paso es construir algo con él. No un script de prueba — un flujo de trabajo real donde Claude Code gestione decisiones en cadena. Si quieres ver ese proceso desde el principio, el curso Construye con IA: De la Idea al Producto con Claude y Specs parte exactamente de aquí.


    FAQ — Preguntas frecuentes sobre Claude Code

    ¿Claude Code funciona con cualquier lenguaje de programación?

    Sí. Claude Code no está limitado a ningún stack. Funciona igual con TypeScript, Python, Go, Rust, Java o cualquier lenguaje que puedas ejecutar desde terminal. Las herramientas como Bash, Glob y Grep operan sobre el filesystem, no sobre el lenguaje. Lo que sí varía es la calidad del output según el lenguaje — para TypeScript y Python la precisión es especialmente alta porque son los lenguajes más representados en el entrenamiento.

    ¿Cuál es la diferencia real entre Sonnet y Opus para trabajo diario?

    En la práctica, para el 90% de las tareas cotidianas no notarás diferencia en calidad. Sí notarás diferencia en velocidad y coste. Opus tarda más y consume más tokens. La diferencia se hace evidente en problemas complejos con mucho contexto: cuando le das un módulo de 3.000 líneas y le pides que entienda las dependencias implícitas antes de refactorizar, Opus razona más profundo. Para añadir un endpoint nuevo a una API que ya funciona, Sonnet es suficiente.

    ¿Cómo evito que Claude Code modifique archivos que no debe tocar?

    Con el CLAUDE.md. Puedes definir explícitamente qué archivos o carpetas son de solo lectura, qué operaciones requieren confirmación explícita tuya antes de ejecutarse, y qué convenciones debe respetar siempre. Claude Code en modo interactivo ya solicita confirmación antes de ejecutar operaciones destructivas — y con autoApproveEdits: false en tu settings.json puedes reforzar ese control para cualquier edición de archivos.

    ¿Claude Code puede trabajar en proyectos con múltiples repositorios?

    Sí, pero con matices. Claude Code opera desde el directorio donde lo lanzas y puede leer rutas relativas o absolutas fuera de él si tienes los permisos correctos. Para proyectos monorepo o arquitecturas con múltiples repos relacionados, la práctica recomendada es lanzarlo desde la raíz del monorepo y gestionar el contexto con @carpetas específicas para cada subtarea. Si trabajas con Angular en un monorepo, el curso de Angular Moderno cubre la estructura de proyectos que mejor se integra con flujos agenticos.

    ¿Cuánto contexto puede manejar Claude Code en una sesión?

    Depende del modelo. Los modelos actuales de Claude tienen ventanas de contexto de 200.000 tokens, lo que equivale a varios cientos de miles de líneas de código. En la práctica, el límite operativo es antes: a partir de cierto volumen, la calidad del razonamiento empieza a degradarse aunque técnicamente quepa más. La buena práctica es ser selectivo con el contexto que cargas — usar @ para incluir solo los archivos relevantes para la tarea actual, no volcar el repositorio entero en cada sesión.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • El Harness: por qué la spec y la arquitectura no son suficientes

    El Harness: por qué la spec y la arquitectura no son suficientes

    Mi workflow completo: de idea a producto en producción con IA

    Hace un año tardaba 2-3 semanas en tener algo desplegado desde una idea nueva.

    Hoy tardo 2-3 días.

    No porque use mejores modelos. Porque cambié el workflow.

    Acá está el proceso completo, sin omitir nada.


    Fase 1 — Captura (30 minutos)

    Antes de abrir el editor, abro un documento en blanco y respondo tres preguntas:

    1. ¿Qué problema concreto resuelve esto?
    2. ¿Quién lo va a usar y en qué contexto exacto?
    3. ¿Qué tiene que funcionar sí o sí para que sea útil desde el día uno?

    Solo eso. Sin pensar en tech stack. Sin pensar en arquitectura.

    Si no puedo responder las tres en 30 minutos, la idea no está lista para construirse.


    Fase 2 — Spec (1-2 horas)

    Con las respuestas anteriores, genero la spec técnica.

    La spec tiene 6 secciones: Visión, Usuarios, Funcionalidades, Flujos, Arquitectura y NFRs.

    No la escribo yo desde cero. La genero con un agente que toma mis respuestas de la Fase 1 como input.

    Luego la reviso y ajusto lo que el agente asumió mal.

    El output: un documento de 2-3 páginas que define qué se construye, para quién, y cómo debe comportarse.


    Fase 3 — Plan técnico (30 minutos)

    Con la spec lista, otro agente genera el plan de implementación.

    No “empieza a codear”. Define:

    • Las fases del proyecto en orden
    • Qué necesita estar listo antes de cada fase
    • Los riesgos técnicos por módulo

    Reviso el plan. Lo ajusto si algo no tiene sentido. Firma.


    Fase 4 — Implementación (el grueso)

    Aquí entra Claude Code.

    No le doy el prompt “hazme la app”. Le doy la spec + el plan + el task específico a implementar en esa sesión.

    Un task. Una sesión. Un output verificable.

    Si el task es “implementar autenticación con GitHub OAuth”, eso es todo lo que hace esa sesión.

    Al final de cada sesión, verifico que lo que se construyó cumple el criterio de aceptación de la spec.

    Si no lo cumple, corrijo antes de avanzar. No acumulo deuda de contexto.


    Fase 5 — Deploy y validación (1-2 horas)

    Deploy con el stack que use el proyecto (Railway, Vercel, Supabase).

    Luego muestro el producto a 2-3 personas del perfil objetivo y les hago una sola pregunta:

    “¿Qué haría que esto fuera indispensable para ti?”

    No “¿te gusta?” ni “¿qué mejorarías?”.

    Esa pregunta específica te da el siguiente ciclo de iteración o te dice que pivotes.


    Lo que hace que este workflow funcione no es la IA.

    Es que la IA nunca opera sin contexto estructurado.

    Cada agente recibe exactamente lo que necesita para hacer su parte. Nada más. Nada menos.

    Sin eso, la IA improvisa. Y cuando improvisa, construye lo que interpreta, no lo que necesitas.


    Si quieres ver este workflow ejecutado en vivo sobre un proyecto real — Stripe webhook receiver + Supabase, desde la spec hasta el deploy — eso es exactamente lo que hacemos el 9 de julio.

    workshop.dominicode.com

  • Crear productos con IA para vender: guía práctica para developers

    Crear productos con IA para vender: guía práctica para developers

    Hace año y medio lancé mi primer producto digital serio. No fue un curso de seis meses de producción. Fue un libro técnico que tardé tres semanas en escribir, validar y subir a Leanpub.

    La primera semana vendió doce copias. Sin ads. Sin lanzamiento masivo. Solo con un post en LinkedIn y un email a mi lista de 800 personas.

    No lo digo para presumir. Lo digo porque ese resultado me demostró algo que hasta entonces no tenía claro: crear productos con IA para vender no requiere un equipo, ni un presupuesto, ni meses de desarrollo. Requiere entender qué problema específico tienes resuelto y qué formato hace que alguien te pague por esa solución hoy.

    El developer que entiende esto en 2026 tiene una ventaja enorme. El que sigue esperando tener "el producto perfecto" antes de vender, va a seguir esperando.

    Crear productos con IA para vender significa usar modelos de lenguaje y herramientas de IA generativa para reducir el tiempo de construcción de productos digitales —libros técnicos, SaaS micro o automatizaciones— de meses a días, sin necesitar un equipo de desarrollo. No es magia: es el mismo ciclo de producto de siempre, comprimido por tecnología.


    El error que comete el 90% de los developers

    El patrón lo he visto muchas veces — en mi comunidad de Labs, en comentarios de YouTube, en DMs. Un developer con 8 o 10 años de experiencia pasa tres meses construyendo una herramienta. Le pone un nombre, le hace un landing, le añade autenticación, le conecta Stripe.

    Lanza. Cero ventas.

    El problema no fue la ejecución técnica. Fue que nunca validó si alguien quería pagar por eso. Construyó la herramienta antes de confirmar que existía un comprador.

    Esto pasa porque los developers somos buenos construyendo y malos vendiendo. Confundimos el placer de construir con la señal de que hay un mercado. No es lo mismo.

    La IA amplifica este error. Ahora puedes construir en días lo que antes tardabas meses. Eso es una ventaja brutal — pero también es una trampa si no cambias el orden de operaciones. Y antes de la herramienta, está la mentalidad: si te interesa entender qué habilidades definen al developer en la era de la IA, tengo un post donde lo desarrollo en detalle.

    Primero el comprador. Después el producto.


    Los 3 tipos de productos que puedes crear con IA para vender

    No todos los productos digitales son iguales. Hay tres categorías con dinámicas muy distintas. Cada una encaja mejor con un momento distinto de tu carrera como creator.

    1. Productos de información

    Son los más rápidos de crear y los más fáciles de validar: cursos, libros técnicos, guías, workshops.

    La IA te permite crear el primer borrador de un libro en un fin de semana. No el libro terminado — el borrador estructurado que tú refinas con tu experiencia real. Esa diferencia es importante: el valor no está en el texto que genera la IA, sino en el criterio técnico que aportas tú.

    Un libro técnico de 50 páginas a 9,99€ puede venderse a 200 personas en su primer mes si ataca un problema muy específico. Son 2.000€ sin mantenimiento, sin soporte técnico, sin servidor.

    Yo uso este formato para probar ideas antes de invertir más tiempo. El libro de Spec-Driven Development nació así: un problema concreto que resuelvo en mi trabajo diario, empaquetado en un formato que alguien puede leer en una tarde.

    2. SaaS micro

    Una herramienta que resuelve un problema específico para un segmento específico. No necesitas construir el próximo Notion. Necesitas construir la herramienta que los diseñadores de tu nicho usan cada semana y que aún no existe — o existe pero con una UX terrible.

    La IA reduce drásticamente el tiempo de desarrollo. Con Claude Code puedo ir de especificación a MVP funcional en menos de dos días. No estoy exagerando. Ese es exactamente el flujo que enseño en el curso Construye con IA: De la Idea al Producto con Claude.

    Pero el SaaS micro solo funciona si tienes una audiencia o un canal para llegar al comprador. Sin distribución, el mejor producto del mundo no vende. Por eso no recomiendo empezar aquí si estás construyendo tu primera fuente de ingresos con productos digitales.

    3. Automatizaciones y sistemas de IA

    Este es el más subestimado y el que crece más rápido en 2025-2026. Empresas pequeñas y medianas pagan entre 500€ y 5.000€ por automatizaciones que les resuelven procesos concretos: desde 500€ para flujos simples de clasificación o notificaciones, hasta 3.000-5.000€ para sistemas con múltiples integraciones o lógica de agente compleja (clasificar emails, procesar facturas, responder soporte con contexto).

    No lo venden como "IA". Lo venden como "te ahorro X horas a la semana en Y tarea".

    Un developer que sabe construir agentes con n8n o con la API de Claude puede empaquetar estas soluciones como producto repetible. Construyes una vez, vendes a varios clientes del mismo sector. Eso es escalabilidad real sin SaaS.


    El orden correcto para crear productos con IA para vender

    Si te saltas este orden, estás desperdiciando tiempo — aunque uses IA.

    1. Identifica el problema con dinero — No "qué puedo construir" sino "qué problema le duele suficiente a alguien como para pagar". La diferencia entre un problema interesante y un problema con dinero es que el segundo tiene consecuencias reales si no se resuelve: tiempo perdido, ingresos perdidos, errores en producción. Pregunta concreta que funciona: ¿en qué tarea has tardado días que otros developers también tardan días? Eso es un producto.

    2. Valida antes de construir — Para productos de información: escribe un post largo sobre el tema, publica un hilo en LinkedIn, mira si hay engagement real. Si nadie pregunta nada, no hay audiencia. Para SaaS micro: busca si hay alternativas de pago. Si existen, hay mercado. Si no existen, puede ser porque no hay mercado — no porque tú hayas encontrado un hueco.

    3. Construye el mínimo vendible, no el mínimo viable — Un MVP técnico no es lo mismo que un producto vendible. El producto vendible tiene un resultado claro para el comprador, un precio, y una forma de pagar. El resto es iteración.

    4. Distribuye antes de lanzar — El lanzamiento no es el día uno de ventas. Es la culminación de semanas de contenido que preparan al comprador. Si nadie sabe que existe tu producto el día que lo publicas, no importa lo bueno que sea.


    La ventaja real del developer que usa IA

    No es velocidad. Es iteración sin miedo.

    Antes, si una idea de producto fallaba, perdías semanas o meses. Ahora, si una idea falla, has perdido dos días. Esa diferencia cambia completamente la ecuación de riesgo.

    Puedo probar tres ideas de producto en el tiempo que antes tardaba en construir una. Y cuando una funciona — cuando alguien paga antes de que esté terminada — sé exactamente dónde poner la energía.

    Esta es la mentalidad del developer product builder: construir rápido, aprender rápido, no enamorarse de la implementación.

    La IA no te convierte en emprendedor. Pero si ya tienes la mentalidad de resolver problemas reales, la IA elimina la mayoría de los cuellos de botella técnicos que antes te frenaban.


    Un ejemplo concreto: cómo nació Markfolio

    Markfolio es una SaaS que construí para transformar ideas y artículos en libros listos para publicar en Amazon KDP. Nació de un problema mío: el proceso de dar formato a un libro para KDP es tedioso, repetitivo y propenso a errores.

    Antes de escribir una línea de código, hablé con cinco personas que publican libros técnicos. Todas tenían el mismo dolor. Eso fue suficiente señal.

    Construí el MVP en cuatro días usando Claude Code como par de programación. No cuatro días de jornada completa — cuatro días trabajando en bloques de dos horas mientras seguía con mis otros proyectos.

    Está en producción, pero no es mi foco principal ahora mismo. Y eso está bien: me ha enseñado más sobre product building en dos meses que cualquier curso de startups.

    Ese es el punto: la IA te da acceso a iterar a velocidad de startups sin el presupuesto de una startup.


    Lo que la IA no puede hacer por ti

    Esto es importante decirlo sin filtros.

    La IA no valida el mercado. Tú tienes que hablar con compradores reales.

    La IA no distribuye tu producto. Tú necesitas una audiencia o un canal.

    La IA no te da criterio sobre qué construir. Ese criterio viene de años entendiendo problemas técnicos reales.

    Por eso este tema no es para developers que llevan seis meses programando. Es para developers que tienen experiencia acumulada y no saben cómo convertirla en algo que genere ingresos fuera de una nómina.

    Si llevas años resolviendo los mismos problemas en empresas, ya tienes el activo más valioso para crear productos. Solo te falta el sistema para empaquetarlo y venderlo.


    Por dónde empezar esta semana

    No mañana. Esta semana.

    Abre un documento en blanco y responde estas tres preguntas:

    1. ¿Qué problema técnico específico he resuelto en los últimos 12 meses que otros developers también tienen?
    2. ¿Hay alguien que pagaría por resolver ese problema más rápido?
    3. ¿Cuál es el formato mínimo que me permitiría vender eso esta semana — un libro, una plantilla, una consultoría, un servicio?

    Si tienes respuestas claras a las tres, tienes un producto.

    Si quieres el sistema completo — desde la especificación hasta el producto publicado usando IA — eso es exactamente lo que construimos en Dominicode Labs: proyectos reales, metodología Spec-Driven, y una comunidad de developers que están haciendo exactamente esto.


    FAQ — Preguntas frecuentes

    ¿Necesito saber programar para crear productos con IA para vender?

    Depende del tipo de producto. Para libros, cursos y guías técnicas, no necesitas código — necesitas criterio. Para SaaS y automatizaciones, tu experiencia como developer es una ventaja directa. La IA reduce la cantidad de código que tienes que escribir, pero no elimina la necesidad de entender la arquitectura del sistema que estás construyendo.

    ¿Cuánto tiempo se tarda en crear un producto vendible con IA?

    Para un libro técnico de 40-60 páginas: entre 1 y 3 semanas si tienes claridad sobre el tema. Para un SaaS micro con funcionalidad básica: entre 3 y 10 días dependiendo de la complejidad. La IA acelera la ejecución, pero la validación del mercado y la distribución toman su propio tiempo — y no se pueden saltear.

    ¿Qué herramientas de IA se usan para construir productos?

    Las más relevantes en 2026 para developers: Claude Code para desarrollo y arquitectura, n8n para automatizaciones, Cursor como IDE con IA integrada, y la API de Anthropic para productos que necesitan razonamiento avanzado. El stack varía según el tipo de producto — tengo un análisis del stack IA agéntico de 2026 donde comparo opciones y cuándo usar cada una. Lo importante es no acumular herramientas antes de tener claridad sobre qué estás construyendo.

    ¿Cómo valido si mi idea de producto tiene mercado antes de construirla?

    Tres señales concretas: alguien ya paga por algo similar (hay mercado), el problema aparece repetidamente en foros, comunidades o Stack Overflow (hay dolor real), o alguien te ha pedido ayuda con ese problema específico en los últimos seis meses (hay demanda activa). Si no encuentras ninguna de las tres, el problema puede ser interesante pero no tiene mercado suficiente.

    ¿Puedo vender un producto construido con IA sin que "se note"?

    Mal planteada, esa pregunta lleva al producto equivocado. La IA es una herramienta de construcción, como lo es un framework o un lenguaje. Lo que el comprador paga es la solución a su problema, no el método con el que fue construida. Si el producto resuelve un problema real con calidad real, nadie pregunta cómo fue construido.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • Automatizar el proceso de desarrollo con IA: de Jira al deploy

    Automatizar el proceso de desarrollo con IA: de Jira al deploy

    Hace tres meses le propuse a un cliente algo que le sonó a ciencia ficción: que el agente iba a leer el ticket de Jira, implementar la feature, abrir el navegador para testearla, hacer el code review y crear el PR en GitHub. Que él solo tendría que revisar y aprobar.

    Su respuesta fue "sí, claro". Con la misma energía con la que alguien te dice "ajá" cuando no te está escuchando.

    Lo puse en marcha. En la primera semana el agente cerró cuatro tickets de forma autónoma. El quinto lo paré yo a mitad porque se estaba inventando un requisito que no estaba en el ticket. Ajusté el prompt. El sexto salió limpio.

    Esto no es el futuro. Es lo que puedes montar hoy con Claude Code, el MCP de Jira, el MCP de Chrome y un CLAUDE.md bien escrito. Y en este post te cuento exactamente cómo funciona el pipeline para automatizar el proceso de desarrollo con IA de principio a fin.

    Un pipeline agentico de desarrollo es un flujo automatizado donde un agente de IA ejecuta de forma autónoma los pasos de implementación, testing y revisión de código a partir de un ticket, reduciendo la intervención humana al momento de aprobar el resultado.

    El problema con el workflow de desarrollo tradicional

    El ciclo habitual de un developer en un equipo tiene un patrón claro: leer el ticket, entender el contexto del código, implementar, escribir el test manual en el navegador, hacer el PR, esperar el code review, corregir los comentarios, mergear, rezar para que el CI pase.

    Cada uno de esos pasos tiene rozamiento. Cambios de contexto. Interrupciones. El developer senior pasa entre un 20% y un 30% de su tiempo en tareas que no son escribir código: leer tickets, crear PRs, hacer reviews de código propio.

    Con agentes, ese porcentaje puede recortarse a la mitad.

    No estoy hablando de reemplazar al developer. Estoy hablando de eliminar la fricción mecánica para que el developer se quede con las decisiones que importan.

    El pipeline completo: de Jira al deploy en seis pasos

    Así es el flujo que tengo montado:

    [Ticket Jira]
         ↓
    [Claude Code lee ticket via MCP Jira]
         ↓
    [Lee CLAUDE.md + contexto del proyecto]
         ↓
    [Implementa la feature o bug fix]
         ↓
    [MCP Chrome: abre navegador, navega, verifica]
         ↓
    [/code-review: detecta problemas antes del merge]
         ↓
    [Crea PR en GitHub con descripción del ticket]
         ↓
    [CI/CD se dispara tras el merge]
         ↓
    [Deploy a producción]
    

    El developer entra en el paso de revisar el PR. Todo lo anterior lo hace el agente.

    Paso 1: leer el ticket de Jira

    Claude Code tiene acceso al MCP de Jira. Cuando invocas el agente con el ID del ticket, extrae la descripción, los criterios de aceptación, el tipo de tarea y cualquier comentario relevante.

    # Invocar el agente con un ticket específico
    claude "Lee el ticket PROJ-412 de Jira e implementa la tarea"
    

    El agente extrae:

    • Descripción de la tarea
    • Criterios de aceptación (los usará para el testing)
    • Labels y tipo (bug, feature, refactor)
    • Comentarios con contexto adicional

    Si los criterios de aceptación están mal escritos o son ambiguos, el agente lo detecta y puede preguntar antes de implementar. Ese comportamiento se configura en el CLAUDE.md del proyecto.

    Paso 2: leer el contexto del proyecto con CLAUDE.md

    El CLAUDE.md es la memoria del agente sobre tu proyecto. Antes de escribir una sola línea de código, Claude Code lee este archivo para entender:

    • Convenciones de nomenclatura
    • Arquitectura del proyecto (qué hace cada capa)
    • Comandos para correr tests y el servidor local
    • Patrones prohibidos o recomendados
    • Cómo se estructuran los PRs en este equipo

    Un CLAUDE.md bien escrito transforma al agente de "asistente genérico" a "developer que conoce el proyecto". La diferencia entre los dos es enorme en producción.

    # CLAUDE.md — ejemplo mínimo
    
    ## Arquitectura
    - Feature modules en `src/features/<nombre>/`
    - Services solo en la capa de aplicación, nunca en componentes
    - Todos los efectos secundarios pasan por el store (NgRx)
    
    ## Comandos importantes
    - Dev server: `bun run dev`
    - Tests: `bun run test`
    - Build: `bun run build`
    
    ## Convenciones de PR
    - Título: `[PROJ-XXX] descripción breve`
    - Descripción: resumen del ticket + cambios técnicos + steps to test
    

    Si quieres ver cómo construir un CLAUDE.md completo para un proyecto real, en el curso Construye con IA lo hago desde cero con un proyecto en TypeScript.

    Paso 3: implementar la feature

    Claude Code implementa la tarea. Lee los archivos relevantes, sigue las convenciones del CLAUDE.md, escribe los tests unitarios si el proyecto los requiere y ejecuta el servidor local para verificar que compila sin errores.

    Aquí es donde el contexto importa más que el modelo. Un agente con buen contexto (CLAUDE.md + ticket detallado) implementa con una tasa de acierto mucho más alta que uno que empieza desde cero.

    El agente también puede hacer preguntas aclaratorias antes de implementar si detecta ambigüedad. Ese comportamiento se configura así en el CLAUDE.md:

    ## Comportamiento del agente
    - Si los criterios de aceptación son ambiguos, pregunta antes de implementar
    - No inventes requisitos que no estén en el ticket
    - Si necesitas crear un nuevo módulo, describe la estructura antes de crearla
    

    Paso 4: testing en el navegador con el MCP de Chrome

    Este es el paso que más sorprende a los developers cuando lo ven por primera vez.

    El MCP de Chrome (servidor MCP que usa Playwright por debajo para controlar el navegador) le da a Claude Code control total: abrir URLs, hacer clic en elementos, rellenar formularios, tomar screenshots, leer el contenido del DOM, verificar mensajes de error en consola.

    El agente usa los criterios de aceptación del ticket como guión de testing. Si el ticket dice "el usuario debe poder filtrar la tabla por fecha y ver solo los registros del rango seleccionado", el agente:

    1. Abre la app en localhost:4200
    2. Navega a la sección de la tabla
    3. Selecciona un rango de fechas
    4. Verifica que los registros mostrados coinciden con el filtro
    5. Toma un screenshot del resultado
    6. Revisa la consola del navegador para detectar errores
    // API de Playwright que ejecuta el servidor MCP internamente
    await page.goto('http://localhost:4200/dashboard/reports');
    await page.click('[data-testid="date-filter"]');
    await page.fill('[data-testid="date-from"]', '2026-01-01');
    await page.fill('[data-testid="date-to"]', '2026-01-31');
    await page.click('[data-testid="apply-filter"]');
    
    const rows = await page.$$('[data-testid="table-row"]');
    // Verifica que todos los rows tienen fechas dentro del rango
    

    Si algo falla, el agente lo reporta, corrige el código y vuelve a ejecutar el test. Es un loop de implementar → testear → corregir que el developer antes hacía manualmente.

    Referencia: Playwright — documentación oficial de automatización de navegadores.

    Paso 5: code review automático antes del PR

    Antes de crear el PR, el agente ejecuta /code-review — un slash command de Claude Code que analiza todos los cambios del diff:

    • Detecta problemas de seguridad (inputs sin sanitizar, secrets hardcodeados)
    • Verifica que se siguen las convenciones del proyecto
    • Revisa cobertura de casos edge
    • Detecta código duplicado o patrones que el equipo tiene como prohibidos

    Si el code review detecta problemas críticos, el agente los corrige antes de crear el PR. Si son sugerencias menores, las incluye como comentarios en la descripción del PR para que el reviewer humano las evalúe.

    Tengo un post completo sobre cómo configurar el agentic code review con Claude Code si quieres profundizar en esa parte del pipeline.

    Paso 6: crear el PR y disparar el CI/CD

    El agente crea el PR en GitHub con:

    • Título siguiendo la convención del proyecto (extraído del ticket)
    • Descripción generada del ticket: contexto, criterios de aceptación, cambios técnicos
    • Screenshot del testing en navegador como evidencia visual
    • Checklist de testing para el reviewer
    # El agente ejecuta esto internamente
    gh pr create \
      --title "[PROJ-412] Filtro por fecha en tabla de reportes" \
      --body "$(cat pr-description.md)" \
      --base main
    

    Cuando el developer aprueba el PR y hace el merge, el CI/CD se dispara automáticamente. GitHub Actions corre los tests, valida el build y despliega a producción. El agente ya no interviene en este paso — el pipeline de CI/CD es responsabilidad del equipo de infraestructura.

    Lo que el developer sigue haciendo

    Dejar claro este punto porque es importante: el agente no reemplaza al developer. El developer hace tres cosas:

    1. Escribir tickets con criterios de aceptación claros. Esto es ahora la habilidad más valiosa. Un ticket ambiguo produce código ambiguo.
    2. Revisar y aprobar el PR. El agente implementa, pero el developer decide si el resultado es correcto.
    3. Mantener el CLAUDE.md actualizado. Las convenciones del proyecto, la arquitectura, los patrones — el agente es tan bueno como el contexto que le das.

    El rol evoluciona de "el que escribe el código" a "el que define qué construir y valida que se construyó bien". Que es, paradójicamente, donde está el valor real de un developer senior.

    En Dominicode Labs estamos implementando este pipeline en proyectos reales con la comunidad — si quieres ver el setup completo con errores incluidos, es donde lo hacemos en directo.

    Cómo empezar a automatizar tu proceso de desarrollo con IA

    No montes el pipeline completo de golpe. Empieza con esto:

    1. Escribe un CLAUDE.md sólido para tu proyecto
    2. Instala el MCP de GitHub en Claude Code
    3. Prueba crear un PR automático desde un cambio pequeño
    4. Añade el MCP de Chrome y testea un flujo simple en el navegador
    5. Conecta Jira cuando los pasos anteriores funcionen de forma estable

    El pipeline completo lleva tiempo afinar. El valor llega antes de tenerlo completo.


    Preguntas frecuentes

    ¿El MCP de Chrome funciona con cualquier framework frontend (React, Vue, Angular)?
    Sí. El MCP de Chrome opera sobre el navegador real, no sobre el framework. No le importa si la app está en Angular, React o Vue — interactúa con el DOM resultante. Solo necesitas que la app esté corriendo en un servidor local accesible.

    ¿Qué pasa si los criterios de aceptación del ticket están mal escritos o son incompletos?
    El agente intentará inferir la intención, pero si la ambigüedad es suficientemente alta, puede preguntar antes de implementar o implementar algo que no era lo esperado. La calidad del output del agente es directamente proporcional a la calidad del input (el ticket). Invertir en escribir buenos tickets es la palanca más subestimada de este pipeline.

    ¿Se puede usar este pipeline sin Jira? ¿Con Linear, GitHub Issues u otras herramientas?
    Sí. Claude Code tiene MCPs para Linear, Asana y GitHub Issues. El principio es el mismo: el agente lee el ticket desde la fuente, extrae los criterios de aceptación y los usa como guión de implementación y testing. La integración específica depende del MCP disponible para cada herramienta.

    ¿Es seguro dejar que el agente tenga acceso a la base de datos o a servicios externos durante el testing?
    No. El testing del agente debe hacerse contra un entorno de desarrollo o staging, nunca contra producción ni contra una base de datos con datos reales. El CLAUDE.md debe especificar explícitamente contra qué entorno corre el agente y qué permisos tiene. El principio de mínimos privilegios aplica igual para agentes que para cualquier proceso automatizado.

    ¿Cuánto tiempo lleva montar este pipeline desde cero?
    El pipeline mínimo (CLAUDE.md + MCP GitHub + PR automático) puede estar funcionando en un día. El pipeline completo con MCP de Jira, MCP de Chrome y code review automático lleva entre una semana y dos de ajuste para que funcione de forma estable en un proyecto real. La mayor parte del tiempo se va en escribir un CLAUDE.md completo y en afinar los prompts para que el agente entienda las convenciones del proyecto.


    Si quieres aprender a construir con IA desde cero hasta producción, echa un vistazo al curso Construye con IA.

    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.

  • LLMs locales en 2026: guía de hardware y modelos

    LLMs locales en 2026: guía de hardware y modelos

    curl -fsSL https://ollama.com/install.sh | sh

    Descargar modelo según tu hardware

    ollama pull phi4-mini # para 8 GB
    ollama pull llama3.1:8b # para 16 GB
    ollama pull qwen3:32b # para 32-48 GB
    ollama pull gemma4:26b # alternativa para 32-48 GB
    ollama pull llama3.1:70b # para 64 GB o AMD Ryzen AI Max+

    Lanzar el modelo

    ollama run qwen3:32b

    
    Una vez que Ollama está corriendo, expone una API REST compatible con el formato de OpenAI en `http://localhost:11434`. Cualquier herramienta que apunte a esa URL puede usar tu modelo local sin cambiar el código de integración.
    
    ### Alternativas a Ollama
    
    - **LM Studio**: interfaz gráfica, ideal para explorar y comparar modelos sin tocar la terminal. Buena opción si quieres probar varios modelos antes de decidir cuál integrar.
    - **MLX**: framework nativo de Apple Silicon. En modelos de menos de 14B es entre un 20% y un 87% más rápido que llama.cpp. Si trabajas exclusivamente en Mac y quieres exprimir el hardware, MLX es la mejor opción para ese rango.
    - **llama.cpp**: más control, más bajo nivel. Útil cuando necesitas cuantización específica o experimentar con configuraciones no estándar.
    
    Para developers que integran modelos en flujos de trabajo, el stack que funciona en 2026 es **Ollama como servidor + tu herramienta habitual como cliente**. Sin más.
    
    ---
    
    ## Cuándo tiene sentido y cuándo no
    
    Esta es la parte que más se omite en los tutoriales.
    
    ### Tiene sentido correr LLMs locales cuando:
    
    - **Privacidad del código**: tienes código propietario o contractualmente restringido que no puede salir de tu máquina. Enviar un contexto de 50.000 tokens con lógica de negocio crítica a la API de terceros es un riesgo que algunas empresas no pueden asumir.
    - **Costo a escala**: si generas miles de peticiones al día en un pipeline automatizado, el coste por token se acumula rápido. Un modelo local bien configurado tiene coste cero por petición una vez amortizado el hardware.
    - **Trabajo offline o con latencia cero**: demos, entornos sin acceso a internet, o flujos donde la latencia de red es un problema real.
    - **Experimentación sin rate limits**: probar prompts, evaluar respuestas, hacer benchmarks a tu ritmo.
    
    ### No tiene sentido cuando:
    
    - **Necesitas calidad frontier para producción**: la diferencia entre un Qwen 3 32B local y Claude Fable 5 en tareas de razonamiento complejo multi-paso sigue siendo real. Para agentes que toman decisiones críticas o generan código de arquitectura compleja, la API sigue ganando. Si quieres integrar la API de Claude en tus proyectos, el [crash course de Claude API para TypeScript](https://www.dominicode.com/posts/claude-api-introduccion-crash-course) cubre el setup completo.
    - **Tienes menos de 16 GB**: con 8 GB la experiencia es frustrante, no productiva.
    - **Tareas de razonamiento complejo**: cadenas de pensamiento largas, análisis que requieren mantener contexto amplio con alta fidelidad. Ahí los modelos frontier siguen siendo superiores.
    
    La pregunta no es "API local o API remota". La pregunta es: ¿qué tarea estás haciendo y cuánto contexto necesitas? Si en el [curso de Construye con IA](https://www.udemy.com/course/construye-con-ia-de-la-idea-al-producto-con-claude-code/?referralCode=AECD9EA3796054DEDD5D) hablo de agentes que procesan código propio en bucles automatizados, el caso de uso para LLMs locales es obvio. Para tareas de planeamiento de arquitectura complejas, Claude sigue siendo la elección correcta.
    
    El stack ideal en 2026 no es elegir uno. Es saber cuándo usar cada uno.
    
    ---
    
    ## El contexto de mercado que importa
    
    El ecosistema de LLMs se fragmenta: los modelos locales, los modelos especializados y las APIs alternativas han madurado lo suficiente para competir en casos de uso concretos. Ya no estamos en el momento en que solo había una opción viable para cada tarea.
    
    Eso es bueno para los developers. Significa que la decisión ya no es "uso OpenAI o no". Es una decisión de ingeniería sobre qué modelo, ejecutado dónde, para qué tarea específica.
    
    En [Dominicode Labs](https://labs.dominicode.com) hemos estado documentando exactamente esos patrones — qué modelos locales integramos en qué partes del pipeline de desarrollo y cómo medimos la diferencia. Si quieres explorar ese material con proyectos reales, ahí está el acceso.
    
    ---
    
    ## FAQ
    
    **¿Qué modelo local es el mejor en 2026 para desarrolladores?**
    
    Depende de tu hardware. Si tienes 32 GB o más, Qwen 3 32B es el más equilibrado: buen razonamiento, soporte de contexto largo y rendimiento estable. Para 16 GB, Llama 3.1 8B sigue siendo sólido. Para trabajo de código específicamente, Qwen 2.5 Coder en su variante 7B o 14B es fuerte para el rango de memoria que ocupa.
    
    **¿Necesito una GPU dedicada para correr LLMs locales?**
    
    No si tienes Apple Silicon. La memoria unificada de los chips M hace que el requisito de "GPU con mucha VRAM" deje de aplicar. En Windows, una RTX 4090 con 24 GB de VRAM sigue siendo el estándar para modelos de 32B, pero el AMD Ryzen AI Max+ 395 con su arquitectura de memoria compartida es una alternativa seria para laptops.
    
    **¿Ollama funciona en Windows?**
    
    Sí. Ollama tiene instalador nativo para Windows. Para GPUs AMD en Windows, el soporte ROCm es inconsistente — si usas hardware AMD en Windows y tienes problemas de rendimiento, considera Linux.
    
    **¿Cuánto tarda en responder un modelo 32B corriendo en local?**
    
    En un MacBook Pro M4 Max con 48 GB, Qwen 3 32B genera aproximadamente 25-35 tokens por segundo, dependiendo de la longitud del contexto. Para conversaciones normales es fluido. Para respuestas muy largas o contextos de 100K+ tokens, es notablemente más lento que la API.
    
    **¿Los modelos locales pueden usarse con herramientas como Cursor o VS Code?**
    
    Sí. Ollama expone una API compatible con el formato de OpenAI. Herramientas que permiten configurar un endpoint de API personalizado (como Continue.dev en VS Code) pueden apuntar directamente a tu instancia local de Ollama.
    
    **¿Vale la pena el hardware nuevo solo para correr LLMs locales?**
    
    Si ya tienes un Mac con 32 GB o más, no necesitas hardware nuevo. Si estás en el mercado de una actualización, el Mac Studio M4 Max con 64 GB es el punto de entrada más potente para correr modelos de 70B con rendimiento real. Para Windows, una RTX 4090 sigue siendo la opción más accesible para modelos de 32B.
    
    ---
    
    *Por [Bezael Pérez](https://dominicode.com) — Developer senior con más de 15 años de experiencia y fundador de Dominicode.*
    
    Si tu siguiente paso es probarlo hoy: corre `ollama pull qwen3:32b` si tienes 32 GB, o `ollama pull llama3.1:8b` si tienes 16 GB. En diez minutos tienes el modelo corriendo. El resto lo tienes en el canal de [YouTube de Dominicode](https://www.youtube.com/@dominicode) — pipelines reales, no teoría.
    
  • RAG vs Fine-tuning: cuándo usar cada uno (guía práctica)

    RAG vs Fine-tuning: cuándo usar cada uno (guía práctica)

    Un cliente me mostró su arquitectura hace unos meses. Había pasado seis semanas haciendo fine-tuning de un modelo para que respondiera preguntas sobre la documentación interna de su empresa.

    Seis semanas. Un dataset de 4.000 pares de pregunta-respuesta construidos a mano. Costes de entrenamiento en GPU. Y al final, el sistema seguía inventándose respuestas cuando la pregunta tocaba un documento que no estaba en el training data.

    Le pregunté por qué no había usado RAG. Me dijo que pensó que fine-tuning era “la solución profesional”. Que RAG era para hacer demos rápidas. Ese malentendido sobre RAG vs Fine-tuning es más común de lo que parece, y sale caro.


    El error conceptual que lo complica todo

    La mayoría de developers que se acercan a este problema lo enmarcan mal desde el principio.

    Piensan en términos de “qué técnica es más potente”. Y ahí ya van por el camino equivocado.

    La pregunta correcta no es cuál es más potente. Es: ¿qué problema tienes exactamente?

    Si tu modelo no sabe cosas que necesita saber — información privada, documentos internos, datos recientes — tienes un problema de conocimiento. RAG lo resuelve.

    Si tu modelo sabe las cosas pero no las comunica como necesitas — tono diferente, formato específico, comportamiento distinto al por defecto — tienes un problema de comportamiento. Fine-tuning lo resuelve.

    Son problemas distintos. Las soluciones no son intercambiables.


    Qué es RAG (Retrieval-Augmented Generation) y cuándo usarlo

    RAG (Retrieval-Augmented Generation) no modifica el modelo. El modelo base sigue siendo exactamente el mismo.

    Lo que hace RAG es intervenir en el momento en que llega una pregunta. Antes de pasársela al modelo, busca en una base de datos vectorial los fragmentos de tus documentos más relevantes para esa consulta, y los inyecta en el prompt. El modelo entonces responde con acceso real a esa información.

    Usuario pregunta: "¿Cuál es la política de devoluciones?"
                             ↓
                 Sistema RAG busca en vectorDB
                             ↓
          Encuentra: chunk del doc "politica-devoluciones-2026.pdf"
                             ↓
        Prompt al modelo: "Contexto: [chunk]. Pregunta: ¿Cuál es...?"
                             ↓
                Modelo responde con información real

    La ventaja clave: tus documentos pueden cambiar mañana. Actualizas la base vectorial. El modelo ya tiene acceso a la nueva información. Sin reentrenar nada.

    Si estás explorando qué modelo usar para el componente generativo, este análisis sobre el mejor modelo LLM local en 2026 te ayuda a elegir sin sobreingenierizar la infraestructura.

    Esto es lo que lo hace ideal para documentación interna, bases de conocimiento, FAQs, soporte técnico — cualquier caso donde la información cambia y necesitas que el modelo cite fuentes reales en lugar de fabricar respuestas.

    El límite de RAG está en que no cambia cómo se comporta el modelo. Si necesitas que responda en un tono muy específico, siga un formato exacto, o haga razonamientos que el modelo base no hace bien de forma natural, RAG no te ayuda. Solo le das más información. No lo entrenas.


    Qué es Fine-tuning de LLMs y cuándo tiene sentido aplicarlo

    Fine-tuning sí modifica el modelo. Tomas un modelo base preentrenado y lo sigues entrenando con tu propio dataset, ajustando sus pesos para que aprenda los patrones que te interesan.

    El resultado es un modelo diferente. Uno que ha interiorizado un estilo, un formato, un tipo de razonamiento específico. No necesitas darle instrucciones en el prompt porque ya las tiene grabadas en sus pesos.

    # Sin fine-tuning: necesitas el prompt completo
    prompt = """Eres un asistente técnico especializado en Kubernetes.
    Responde siempre con: 1) causa del problema, 2) solución paso a paso, 
    3) cómo prevenirlo. Usa terminología técnica precisa. No añadas 
    disclaimers. El tono es directo, de senior a senior.
    
    

    Problema: Mi pod no arranca después de actualizar la imagen..."""

    # Con fine-tuning: el modelo ya sabe cómo comportarse prompt = "Problema: Mi pod no arranca después de actualizar la imagen..."

    El modelo fine-tuneado responde directamente en el formato correcto porque ese comportamiento está en sus pesos. No porque se lo estés recordando en cada llamada.

    Lo que fine-tuning no resuelve: inyectar conocimiento factual nuevo. Si entrenas el modelo en el estilo de tu empresa pero no en los documentos de tu empresa, seguirá sin saber qué contienen esos documentos. Habrá aprendido a comunicarse como tú quieres, pero no a responder con información real que no tenía.


    RAG vs Fine-tuning: la matriz de decisión con cuatro casos reales

    Hay cuatro combinaciones que aparecen una y otra vez en proyectos reales. Aquí están con sus soluciones.

    Caso 1: Chatbot sobre documentación interna

    Necesitas que el modelo responda preguntas sobre tus PDFs, wikis, Notion, Confluence. La información cambia regularmente. El tono puede ser el del modelo base.

    Solución: RAG. Indexas los documentos en una vectorDB (Pinecone, pgvector, Weaviate), configuras el pipeline de retrieval, y el modelo responde con fuentes reales. No reentrenar nada.

    Caso 2: Generador de código en el estilo de tu empresa

    Quieres que el modelo genere código que siga tus convenciones internas, use tus abstracciones propias, evite los patrones que prohíbes. El modelo base lo entiende pero tienes que recordárselo en cada prompt.

    Solución: Fine-tuning. Un dataset de ejemplos de código en tu estilo — antes/después — y el modelo interioriza esas preferencias. El prompt se simplifica radicalmente.

    Caso 3: Asistente de soporte que responde sobre tus productos Y en tu tono

    Quieres las dos cosas: información factual sobre tus productos (que cambia) y un comportamiento de comunicación muy específico (directo, sin ambigüedades, con formato concreto).

    Solución: Fine-tuning + RAG. Fine-tuning para el comportamiento y el formato. RAG para la información factual. Son complementarios, no excluyentes.

    Caso 4: Clasificador de texto o extractor de entidades

    Necesitas que el modelo clasifique tickets de soporte, extraiga entidades de contratos, o haga tareas de NLP muy específicas.

    Solución: Fine-tuning en casi todos los casos. Para tareas de clasificación y extracción, un modelo fine-tuneado en tu dominio supera consistentemente a uno general con prompts elaborados, y además es más barato en inferencia porque los prompts son más cortos.


    Los costes reales — lo que nadie te dice antes de empezar

    Costes de RAG:

    • Configurar el pipeline de chunking, embedding y retrieval: 2-5 días de desarrollo
    • Inferencia: coste del modelo base + coste de las llamadas a la vectorDB (bajo)
    • Mantenimiento: actualizar la base vectorial cuando cambian los documentos (automatizable)
    • Problema principal: calidad del retrieval — si buscas mal, el modelo responde mal aunque los documentos sean perfectos

    Costes de Fine-tuning:

    • Construir el dataset de entrenamiento: semanas (es el cuello de botella real)
    • Entrenamiento: desde $50 hasta miles de dólares dependiendo del modelo y el tamaño del dataset
    • Inferencia: más cara que el modelo base porque tienes que hostear tu propio modelo o pagar por el endpoint custom
    • Problema principal: degradación con el tiempo — si tu tarea evoluciona, tienes que reentrenar

    La mayoría de proyectos que han hecho fine-tuning cuando lo que necesitaban era RAG han pagado semanas de trabajo y costes de entrenamiento para resolver un problema que RAG hubiera resuelto en cuatro días.


    El árbol de decisión que uso en consultoría

    Cuando alguien me pregunta qué usar, le hago estas cuatro preguntas en orden:

    1. ¿Tu problema es que el modelo no tiene la información o que no se comporta como quieres?

    • No tiene la información → RAG
    • No se comporta bien → Fine-tuning

    2. ¿La información cambia con frecuencia?

    • Sí → RAG (actualizar embeddings es trivial vs. reentrenar)
    • No → Fine-tuning empieza a tener más sentido

    3. ¿Tienes datos de entrenamiento de alta calidad?

    • No los tienes → empieza con RAG mientras los recopilas
    • Sí los tienes → Fine-tuning es viable

    4. ¿Tienes restricciones de latencia o coste de inferencia?

    • Sí, necesitas prompts muy cortos → Fine-tuning reduce el prompt dramáticamente
    • No es crítico → RAG es suficiente

    En la práctica, el 70% de los casos que veo en producción son candidatos a RAG, no a fine-tuning. Fine-tuning es potente pero requiere un problema muy bien definido, datos de calidad y tiempo para construirlos.


    Qué pasa cuando combinas los dos

    La combinación más efectiva en sistemas de producción serios sigue un patrón concreto. Y es parte de una arquitectura más amplia — si quieres entender cómo el LLM encaja con el resto del sistema, el post sobre qué es un agent harness lo explica con detalle.

    • Fine-tuning para que el modelo entienda el dominio, la terminología y el formato de respuesta esperado
    • RAG para que el modelo tenga acceso a la información factual actualizada

    Un ejemplo real: un asistente jurídico. Fine-tuneado para entender terminología legal española, responder en formato jurídico y estructurar los análisis como lo haría un abogado. RAG conectado a la base de legislación actualizada y a los expedientes del despacho.

    El modelo habla como un jurista (fine-tuning). Responde con la ley real y los documentos del caso (RAG). Ninguna de las dos técnicas sola lo consigue.

    Esta es la arquitectura que más vemos en productos de IA serios. No es glamorosa. Pero funciona. En el curso Construye con IA: de la idea al producto con Claude Code, trabajo este tipo de decisiones de arquitectura desde la fase de especificación — antes de escribir una línea de código — para que no llegues a la semana seis arrepintiéndote de la técnica que elegiste.


    Tabla comparativa RAG vs Fine-tuning

    RAG Fine-tuning
    Problema que resuelve El modelo no tiene la información El modelo no se comporta como quieres
    Modifica el modelo No
    Cuándo usar Datos dinámicos, documentos, bases de conocimiento Estilo, formato, comportamiento consistente
    Coste de inicio Bajo-medio (pipeline) Alto (dataset + entrenamiento)
    Mantenimiento Fácil (actualizar vectorDB) Costoso (reentrenar cuando cambia el problema)
    Tiempo hasta producción Días Semanas
    Combinar con el otro

    Guarda esta tabla. Te va a ahorrar más de una conversación.


    FAQ

    ¿Puedo usar RAG con cualquier LLM?

    Sí. RAG es agnóstico al modelo. Funciona con GPT-4, Claude, Gemini, Llama, Mistral o cualquier modelo que acepte un prompt de texto. Lo único que necesitas es que el modelo tenga una ventana de contexto suficiente para recibir los chunks recuperados junto con la pregunta. Los modelos modernos (128k-200k tokens) raramente tienen problemas con esto.

    ¿El fine-tuning de GPT-4 o Claude vale la pena frente a usar el modelo base con un buen prompt?

    En la mayoría de casos de uso, un buen prompt de sistema con ejemplos (few-shot prompting) iguala o supera al fine-tuning cuando el dataset de entrenamiento es pequeño (menos de 1.000 ejemplos). Fine-tuning empieza a tener sentido claro cuando tienes +5.000 ejemplos de calidad, cuando el coste de inferencia del prompt largo es un problema real, o cuando necesitas consistencia de comportamiento imposible de garantizar solo con prompts.

    ¿RAG siempre “alucina” menos que el modelo base?

    RAG reduce alucinaciones relacionadas con hechos específicos de tus documentos — porque el modelo tiene el texto real delante. Pero no elimina las alucinaciones del modelo base sobre razonamientos o inferencias. Si el modelo alucina porque hace mal el razonamiento lógico, RAG no te ayuda. Ese es un problema de capacidad del modelo, no de conocimiento.

    ¿Qué vectorDB recomendas para empezar?

    Para proyectos nuevos: pgvector si ya usas PostgreSQL (cero infraestructura adicional), o Pinecone si quieres un servicio gestionado sin fricción operativa. Weaviate y Chroma son buenas opciones open-source si necesitas auto-hosting. Evita sobre-ingenierizar esto al principio — pgvector resuelve el 80% de los casos sin añadir complejidad. Puedes consultar la documentación oficial de pgvector para la instalación y configuración básica.

    ¿Cuánto cuesta hacer fine-tuning con GPT-4o mini o Llama 3?

    GPT-4o mini fine-tuning en OpenAI cuesta aproximadamente $3-5 por millón de tokens de entrenamiento (junio 2026). Un dataset de 10.000 ejemplos con prompts de 500 tokens cada uno te sale a menos de $30 de entrenamiento. El coste real no es el GPU — es el tiempo de construir el dataset de calidad. Con Llama 3, puedes hacer fine-tuning con frameworks como Unsloth en una GPU A100 por $2-4/hora. Un run de fine-tuning de 3-4 horas es completamente asequible.

    ¿RAG vs Fine-tuning cambia con los modelos de razonamiento (o1, Gemini Thinking)?

    Sí, hay un matiz importante. Los modelos de razonamiento son mucho mejores siguiendo instrucciones complejas en el prompt, lo que reduce la necesidad de fine-tuning para casos de comportamiento. Pero siguen sin tener acceso a información privada o actualizada — ahí RAG sigue siendo indispensable. El fine-tuning con modelos de razonamiento es técnicamente más complejo y menos documentado a fecha de hoy.


    Si quieres ver estos patrones aplicados en proyectos reales con código y arquitectura completa, en Dominicode Labs trabajamos este tipo de decisiones técnicas con la comunidad. Proyectos reales, problemas reales, decisiones que puedes aplicar esta semana.


    Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.