supafast-ui · sub-skill: STACK TECNOLÓGICO
El stack exacto de apps/performancetv. No sustituir piezas (sobre todo: base-ui ≠ Radix,
Tailwind v4 ≠ v3). Versiones reales de package.json (rangos ^, ajustar a lo instalado).
Núcleo
| Pieza | Versión | Rol |
|---|---|---|
| React | ^19.0.0 |
UI (+ react-dom) |
| TypeScript | ~5.8.3 |
tipado, strict |
| Vite | ^6.3.1 |
dev server + build |
| react-router | ^7.5.0 |
routing (paquete react-router, no react-router-dom) |
Estilos / UI
| Pieza | Versión | Notas |
|---|---|---|
| tailwindcss | 4.2.1 |
v4 CSS-first, sin tailwind.config.js; tokens en index.css |
| @tailwindcss/vite | 4.2.1 |
plugin oficial (no PostCSS) |
| tw-animate-css | ^1.4.0 |
utilidades de animación (entradas/salidas de overlays) |
| shadcn | ^4.0.5 |
estilo base-nova, baseColor neutral (ver components.json) |
| @base-ui/react | ^1.3.0 |
primitivas headless — NO Radix. useRender/mergeProps, data-checked |
| class-variance-authority | ^0.7.1 |
variantes de componentes (cva) |
| clsx + tailwind-merge | ^2.1.1 / ^3.5.0 |
cn() en @/shared/lib/utils |
| lucide-react | ^0.487.0 |
iconos (size-4 por defecto) |
| @fontsource-variable/geist | ^5.2.8 |
fuente sans (geist-mono ^5.2.7 para mono) |
Estado / datos
| Pieza | Versión | Rol |
|---|---|---|
| @tanstack/react-query | ^5.74.4 |
server state (+ react-query-devtools) |
| zustand | ^5.0.3 |
estado global de cliente |
| axios | ^1.13.6 |
cliente HTTP |
| date-fns | ^4.1.0 |
fechas |
Gráficas
- recharts
^3.8.0— gráficas principales (series usanvar(--chart-series), vercolors.md). - chart.js
^4.5.1+ react-chartjs-2^5.3.1— casos puntuales. - react-day-picker
^9.14.0— calendario/date range (componenteui/calendar.tsx).
Tooling
- ESLint
^10.2.1+typescript-eslint+eslint-plugin-react-hooks+eslint-plugin-react-refresh. - Node ≥ 22, pnpm 11 (monorepo). Nunca npm/yarn.
Scripts (package.json)
{
"dev": "vite", // dev server :5174
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
}
Desde la raíz del monorepo: pnpm --filter @fenix/performancetv <script>.
Alias de imports — @/ → src/
Definido en dos sitios (deben coincidir):
// vite.config.ts
resolve: { alias: { '@': path.resolve(__dirname, './src') } }
// tsconfig(.app).json
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] }
Uso: import { Button } from '@/shared/components/ui/button'. Siempre @/…, nunca rutas relativas largas.
Config de Vite (resumen)
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
export default defineConfig(({ mode, command }) => ({
plugins: [react(), tailwindcss()],
resolve: { alias: { '@': path.resolve(__dirname, './src') } },
// server (solo dev): port 5174 strictPort + proxy con inyección de cookie DEV_AUTH_COOKIE
}))
- Dev server fijo en :5174 (
strictPort). - Proxy dev a backends remotos (
/api/auth,/api,/fenix) inyectando la cookieDEV_AUTH_COOKIEpara evitar CORS/SameSite en localhost (ver memoria del proyecto sobre el proxy local).
Organización del código (feature-first)
src/<feature>/{components,hooks,api,services,lib,types,store,pages} (p.ej. objectives/, campaigns/).
Lo transversal vive en src/shared/ (components/ui, components/data-table, lib, api). Alias del
components.json: @/shared/components, @/shared/components/ui, @/shared/lib/utils, @/shared/hooks.
Reglas
- No añadir Radix, styled-components, Emotion, CSS Modules ni Tailwind v3. El estilo es base-ui + Tailwind v4.
- Server state → React Query; estado de cliente → Zustand. No reinventar fetching ni meter estado de servidor en Zustand.
- Iconos solo de
lucide-react. Fechas condate-fns. - Imports con alias
@/. ESM. Node ≥ 22 + pnpm.