Base UI, tests, IA y observabilidad
Nueva capa de primitivos, 183 tests, un asistente de IA en streaming y errores self-hosted. Más una tanda de majors y cuatro bugs que heredaba cualquier proyecto derivado.
La primera versión desde abril, y la más grande hasta ahora. Cambia la capa de primitivos, añade las tres cosas que hoy se esperan de un kit SaaS de pago y arregla cuatro bugs que venía heredando cualquier proyecto arrancado con este boilerplate.
Base UI sustituye a Radix
shadcn/ui hizo Base UI su opción por defecto en julio. Base UI lo construye el mismo equipo que hizo
Radix, y reduce 24 paquetes @radix-ui/* a uno solo. Treinta y un componentes migrados.
El único cambio que vas a notar es asChild, que pasa a ser render:
<Button asChild>
<Link href="/x">Texto</Link>
</Button>
// pasa a ser
<Button render={<Link href="/x" />}>Texto</Button>
Dos componentes se quedan en Radix a propósito: aspect-ratio, que no tiene equivalente en Base UI,
y label, cuya versión de Base UI solo funciona dentro de un provider Field.Root.
Tests, por fin
La versión anterior traía un comando test con un único fichero detrás. Esta trae 166 tests
unitarios en Vitest y 17 end-to-end en Playwright, que cubren registro, onboarding, login y
navegación del dashboard, con GitHub Actions ejecutando lint, tipos, tests y e2e contra un Postgres
real.
Un asistente de IA que se cobra solo
Un chat en streaming en /dashboard/ai construido sobre AI SDK 7, con OpenAI o Anthropic según
una variable de entorno. Está enchufado al sistema de créditos que ya traía la parte de pagos, en
vez de inventar un segundo concepto de facturación.
Dos decisiones deliberadas: la medición solo se aplica si hay un proveedor de pagos configurado, así que un proyecto que todavía no vende nada sigue teniendo asistente; y los créditos se cobran después del stream, porque el recuento de tokens no existe hasta que termina.
Observabilidad que puedes alojar tú
Todos los kits de la competencia dan por hecho Sentry cloud. Este da por hecho Docker en tu propio
VPS, así que la opción por defecto es GlitchTip — compatible con los SDK de Sentry, mismo
código, distinto DSN — con su fichero de compose para levantarlo. Instrumentación con OpenTelemetry,
logs estructurados sobre pino detrás de la misma API del logger de siempre, y cada logger.error
convertido en incidencia sin tocar una sola llamada.
Cuatro bugs que venías heredando
prisma/migrations/estaba en.gitignore. Cuatro migraciones sin versionar, existían en una sola máquina.createApiHandlerdevolvía un 500 en cualquier POST sin body.verifyCsrfTokenlanzabaRangeErrorsi las longitudes no coincidían, en vez de devolverfalse.garage-setupno arrancaba nunca. La imagen es distroless, así que el servicio de compose con un entrypoint de shell fallaba en cadabun docker:up. El almacenamiento local se configura ahora conbun storage:setup.
Actualizaciones y bajas
React 19.3, Stripe 22, Polar SDK 0.49, react-email 6, lucide-react 1 e isomorphic-dompurify 4 — que por sí solo cierra 34 avisos de seguridad, dos de ellos XSS en el sanitizador del blog. Node 22.22 es el nuevo mínimo.
Se van: Phosphor Icons (dos librerías de iconos en un mismo producto), y jscpd y madge, cuyo
trabajo ya hacía ESLint.
Lo que no ha entrado, y por qué
ESLint 10 y TypeScript 7 están los dos estables y ninguno es usable aquí. eslint-config-next
depende de eslint-plugin-react, cuya versión estable se queda en ESLint 9.7. TypeScript 7 no
publica API programática, así que typescript-eslint directamente no puede ejecutarse sobre él. Los
dos bloqueos son de upstream.
next-intl queda fijado en 4.14.1. A partir de la 4.14.6, getTranslations() dentro de
generateMetadata() cuenta como dato de runtime con Cache Components y el build de producción falla
al prerenderizar. Conviene saberlo porque compila bien y solo falla en la generación estática:
tsc, bun dev y el linter pasan todos.
Prisma 8 sigue siendo release candidate, y es una reescritura más que una actualización. Nos quedamos en la 7.