El experimento
Queriamos saber cuanto tardabamos en tener un dashboard funcional desde cero. No un mockup, no un wireframe en Figma — un dashboard real con autenticacion, datos desde una base de datos, rutas protegidas y componentes decentes.
Las herramientas: create-t3-app para el scaffold y Claude Code como asistente de desarrollo en terminal. El resultado fue un prototipo operativo en una tarde. Pero no todo salio limpio.
Por que T3 Stack
El T3 Stack combina Next.js, TypeScript, tRPC, Prisma, Tailwind CSS y NextAuth.js. La gracia no es que sean tecnologias nuevas — es que vienen integradas con type safety de punta a punta. Cambias un campo en el schema de Prisma y TypeScript te grita en el frontend si no actualizas el componente que lo consume.
Para prototipar rapido, eso es clave. No pierdes tiempo debuggeando tipos que no calzan entre backend y frontend porque tRPC los comparte automaticamente. El contrato entre cliente y servidor es el mismo tipo de TypeScript.
pnpm create t3-app@latest mi-dashboard --CI --trpc --tailwind --prisma --nextAuthCon ese comando tienes un proyecto con autenticacion (NextAuth.js con Discord como provider por defecto), un ORM configurado (Prisma), una API type-safe (tRPC), y estilos listos (Tailwind). En menos de un minuto.
Claude Code como copiloto
Aca es donde el flujo cambia. En vez de armar todo a mano, le delegamos a Claude Code las tareas repetitivas y de scaffolding.
El schema de Prisma
Le pedimos que extendiera el schema para un dashboard de gestion de proyectos. Le dimos contexto minimo: “necesitamos proyectos, tareas y usuarios asignados”.
// Lo que genero Claude Code en ~30 segundos
model Project {
id String @id @default(cuid())
name String
description String?
status ProjectStatus @default(ACTIVE)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tasks Task[]
createdBy User @relation(fields: [createdById], references: [id])
createdById String
}
model Task {
id String @id @default(cuid())
title String
description String?
status TaskStatus @default(TODO)
priority Priority @default(MEDIUM)
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
assignee User? @relation("assignedTasks", fields: [assigneeId], references: [id])
assigneeId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum ProjectStatus {
ACTIVE
ARCHIVED
COMPLETED
}
enum TaskStatus {
TODO
IN_PROGRESS
DONE
}
enum Priority {
LOW
MEDIUM
HIGH
}Bien hecho? Si, en general. Pero tuvimos que ajustar las relaciones con User porque el schema base de NextAuth ya tiene campos en el modelo User y Claude Code no siempre maneja bien la integracion con modelos preexistentes. Tocamos dos relaciones a mano. Tiempo perdido: 5 minutos. Tiempo ahorrado: 15.
Los routers de tRPC
Aca es donde Claude Code brilla. Le dijimos: “crea un router de tRPC para proyectos con CRUD completo, protegido con sesion”.
// src/server/api/routers/project.ts
import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
export const projectRouter = createTRPCRouter({
getAll: protectedProcedure.query(async ({ ctx }) => {
return ctx.db.project.findMany({
where: { createdById: ctx.session.user.id },
include: { tasks: true },
orderBy: { createdAt: "desc" },
});
}),
create: protectedProcedure
.input(z.object({
name: z.string().min(1),
description: z.string().optional(),
}))
.mutation(async ({ ctx, input }) => {
return ctx.db.project.create({
data: {
...input,
createdById: ctx.session.user.id,
},
});
}),
// ... update, delete, getById
});El patron protectedProcedure ya viene en el scaffold de T3. Claude Code lo uso correctamente porque leyo el contexto del proyecto. No invento un middleware de autenticacion nuevo — uso el que ya existia. Eso es lo que lo diferencia de copiar snippets de un chat.
Componentes del dashboard
Para el frontend le pedimos componentes con Tailwind y Lucide para iconos. El flujo fue:
- “Crea un componente ProjectCard que muestre nombre, estado, cantidad de tareas y un badge de prioridad”
- Claude Code lee los tipos generados por tRPC, usa los mismos tipos en el componente
- Genera el componente con Tailwind, importa los iconos de Lucide
// BIEN -- usa los tipos inferidos de tRPC
import type { RouterOutputs } from "~/utils/api";
type Project = RouterOutputs["project"]["getAll"][number];
// MAL -- define tipos a mano que se desincronicen
interface Project {
id: string;
name: string;
// ... se desactualiza cuando cambias el schema
}Ese detalle importa. Si el componente usa los tipos inferidos de tRPC, cuando cambias el schema de Prisma el compilador te avisa en el frontend. Si defines tipos a mano, pierdes la cadena de type safety que es la razon de usar T3 en primer lugar.
Lo que no funciono
Estilos inconsistentes
Claude Code genero componentes que funcionaban, pero cada uno tenia su propio criterio de spacing, colores y border radius. Sin un sistema de diseno definido o un archivo de configuracion de Tailwind claro, cada componente parecia de un proyecto diferente.
La leccion: antes de pedirle componentes, define tu tailwind.config.ts con los colores, espaciados y radios que vas a usar. O mejor, dale un componente de referencia y dile “sigue este estilo”. Sin esa guia, cada componente es una improvisacion.
Logica de negocio compleja
Para el CRUD basico, impecable. Pero cuando le pedimos logica mas compleja — “cuando una tarea se marca como DONE, actualiza el porcentaje de completitud del proyecto y notifica al creador” — el resultado necesito reescritura. No porque el codigo fallara, sino porque las decisiones de donde poner esa logica (router, service layer, event) las tiene que tomar un humano con contexto de negocio.
Migraciones de Prisma
Claude Code puede generar schemas, pero no siempre entiende el estado actual de las migraciones. Nos genero un cambio que requeria una migracion destructiva en un campo que ya tenia datos. En un prototipo da igual. En produccion habria sido un problema.
# Siempre revisar antes de aplicar
npx prisma migrate dev --name add-tasks --create-only
# Leer el SQL generado antes de confirmarEl flujo que nos funciono
Despues de la primera iteracion, ajustamos el proceso:
- Scaffold con create-t3-app — el boilerplate inicial, sin tocar nada
- Definir el schema de Prisma a mano — los modelos de datos son decisiones de arquitectura, no scaffolding
- Claude Code para los routers de tRPC — CRUD, validaciones con Zod, queries. Esto es repetitivo y lo hace bien
- Claude Code para componentes — pero con un componente de referencia como guia de estilo
- Logica de negocio a mano — las reglas del dominio las escribe el equipo
- Claude Code para tests — generar tests unitarios de los routers funciona sorprendentemente bien
El patron es claro: lo repetitivo y estructurado se delega. Lo que requiere criterio se hace a mano. Es la misma logica de nuestro post sobre Claude Code — excelente para implementar, no para decidir.
Los numeros
No medimos con cronometro, pero la estimacion honesta del tiempo es esta:
| Tarea | Sin Claude Code | Con Claude Code |
|---|---|---|
| Scaffold inicial | 5 min | 5 min |
| Schema Prisma (5 modelos) | 30 min | 10 min + 5 min ajustes |
| Routers tRPC (CRUD x3) | 90 min | 15 min + 10 min review |
| Componentes UI (8) | 120 min | 30 min + 20 min ajustes |
| Auth y rutas protegidas | 45 min | Incluido en scaffold |
| Total | ~5 horas | ~1.5 horas |
El asterisco: la version “con Claude Code” todavia necesita revision humana en cada paso. No es automatico. Pero la reduccion de tiempo es real, especialmente en el codigo estructurado y repetitivo.
Cuando tiene sentido este approach
Prototipar con T3 + Claude Code tiene sentido cuando:
- Necesitas validar una idea rapido con un prototipo funcional, no un mockup
- Tu equipo ya conoce TypeScript y el ecosistema React/Next.js
- El dominio del proyecto se puede modelar con CRUD basico al principio
- Quieres type safety desde el dia uno para no pagar deuda tecnica despues
No tiene sentido cuando:
- El proyecto tiene logica de negocio compleja desde el inicio
- Necesitas un stack distinto (Go, Python, etc.)
- Tu equipo no esta comodo revisando y ajustando codigo generado por IA
- El “prototipo” va directo a produccion sin pasar por refactoring
La velocidad del prototipo no reemplaza la calidad del producto. Pero tener algo funcional en una tarde cambia la conversacion con el equipo y con los stakeholders. Discutir sobre algo que se puede tocar es mas productivo que discutir sobre un documento.
T3 te da la estructura type-safe. Claude Code te da las manos extra. El criterio de que construir y como lo sigues poniendo tu.
Fuentes:



