Desarrollo Web Frontend
Parte 2
Clase 5 — Frameworks CSS, ecosistema JavaScript y TypeScript
Objetivos de aprendizaje
Al terminar esta clase, serás capaz de elegir herramientas modernas y adoptar tipado estático con TypeScript.
Frameworks CSS
Comparar Tailwind y Bootstrap, y decidir cuándo usar cada uno.
Ecosistema JS
Entender el panorama actual: React, Vue, Angular y Svelte.
TypeScript
Conocer las ventajas del tipado estático sobre JavaScript puro.
Migración
Escribir tus primeras funciones e interfaces en TypeScript.
Frameworks CSS
Estilos predefinidos que aceleran el desarrollo visual. Tres enfoques que conviene conocer:
Componentes predefinidos
Clases que representan componentes completos (botones, cards, modales). Rápido pero menos personalizable. Bootstrap.
Utility-first
Clases utilitarias muy pequeñas que compones. Máxima personalización con CSS final mínimo. Tailwind.
Lo mejor de los dos
Componentes semánticos sobre Tailwind, con temas integrados. Velocidad de Bootstrap + flexibilidad de Tailwind. DaisyUI.
Bootstrap — el veterano
Creado por Twitter en 2011. Filosofía: componentes listos para usar con clases semánticas de alto nivel.
<!-- Botón --><button class="btn btn-primary btn-lg"> Click aquí</button><!-- Card --><div class="card"> <div class="card-body"> <h5 class="card-title">Título</h5> <p class="card-text">...</p> </div></div>Ventajas
- • Rápido para prototipos
- • Componentes listos para usar
- • Documentación excelente
- • Funciona vía CDN sin build tools
Desventajas
- • Los sitios tienden a verse "todos iguales"
- • Archivo CSS pesado por defecto
Tailwind CSS — la revolución utility-first
Compones cada diseño combinando clases de utilidad. El compilador solo incluye en el CSS final las clases que realmente usas.
<!-- Botón --><button class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors"> Click aquí</button><!-- Card --><div class="max-w-sm rounded-lg shadow-lg bg-white p-6"> <h3 class="font-bold text-xl">...</h3></div>Ventajas
- • Diseños totalmente personalizados
- • CSS final muy pequeño (purga automática)
- • Sin conflictos de nombres de clase
- • Ideal para React, Vue y proyectos modernos
Desventajas
- • HTML verboso
- • Curva de aprendizaje inicial
DaisyUI — componentes sobre Tailwind
Plugin de Tailwind que añade clases semánticas (btn, card,modal) y un sistema de temas. Mantienes la flexibilidad de Tailwind y escribes mucho menos.
<!-- Botón con DaisyUI --><button class="btn btn-primary"> Click aquí</button><!-- Card con DaisyUI --><div class="card bg-base-100 shadow-lg"> <div class="card-body"> <h3 class="card-title">Título</h3> <p>...</p> </div></div><!-- Cambia de tema con un atributo --><html data-theme="dark">Facilidades sobre Tailwind
- • +60 componentes (btn, card, modal, drawer, alert...)
- • +35 temas listos (light, dark, cupcake, dracula...)
- • Sistema de colores semánticos (
primary,accent...) - • HTML mucho menos verboso que Tailwind puro
- • Sigue siendo 100% Tailwind: puedes mezclar utilidades
Lo usamos en este curso
Estas mismas slides están construidas con Tailwind + DaisyUI: las clasescard, badge, btn y alertque ves vienen de DaisyUI.
¿Cuándo usar cada uno?
| Situación | Recomendación |
|---|---|
| Prototipo rápido | Bootstrap |
| Panel de administración | Tailwind + DaisyUI |
| Sitio con diseño totalmente único | Tailwind |
| Proyecto con React o Vue (rápido y bonito) | Tailwind + DaisyUI |
| Necesitas múltiples temas (light/dark...) | Tailwind + DaisyUI |
| Sin build tools (solo CDN) | Bootstrap |
Tendencia 2026
Tailwind ha superado a Bootstrap para nuevos proyectos. El 80% de los proyectos con React o Vue lo eligen por defecto, y muchos lo combinan conDaisyUI para evitar repetir las mismas utilidades.
Componentes reutilizables
Un componente es una pieza autónoma de interfaz — HTML, CSS y lógica empaquetados juntos — que se puede usar en muchos lugares con diferentes datos.
Piezas de LEGO
Pequeñas, encajables y reutilizables. Combinas pocas piezas para construir cosas grandes.
Anatomía
Estructura (HTML), apariencia (CSS) y comportamiento (JS) viviendo en un único archivo.
Por qué
Escribes una vez, usas muchas. Cambios en un único sitio se reflejan en toda la app.
Antes de los frameworks
Sin componentes, copiabas y pegabas el mismo HTML en cada página. Un cambio visual obligaba a editar decenas de archivos. Los frameworks JS resolvieron este problema estandarizando el patrón.
Props: parametrizar un componente
Las props son los argumentos de entrada de un componente. Le dicen qué datos mostrar en cada uso.
// Un componente = una funciónfunction Boton({ texto, color }) { return ( <button class={`btn ${color}`}> {texto} </button> );}// El mismo componente, datos distintos<Boton texto="Guardar" color="primary" /><Boton texto="Cancelar" color="ghost" /><Boton texto="Borrar" color="error" />// Composición: un componente// usa a otrosfunction Modal({ titulo }) { return <><h2>{titulo}</h2> <Boton texto="OK" .../></>;}Idea clave
Cada framework (React, Vue, Angular, Svelte) resuelve este mismo problema — definir componentes con props y componerlos — con su propia sintaxis. Una vez entiendes el patrón, cambiar de framework es cuestión de traducir.
Frameworks JavaScript
Herramientas que organizan el código en componentes reutilizables, gestionan el estado y actualizan la interfaz automáticamente.
React
Meta · 2013
Vue
Evan You · 2014
Angular
Google · 2016
Svelte
Rich Harris · 2016
React y Vue — los más populares
function Saludo({ nombre }) { const [cuenta, setCuenta] = useState(0); return ( <div> <h1>Hola, {nombre}!</h1> <p>Clics: {cuenta}</p> <button onClick={() => setCuenta(cuenta + 1)}>+1</button> </div> );}<template> <div> <h1>Hola, {{ nombre }}!</h1> <button @click="cuenta++"> Clics: {{ cuenta }} </button> </div></template><script setup>import { ref } from 'vue';const nombre = 'Mundo';const cuenta = ref(0);</script>Angular y Svelte — el empresarial y el retador
Angular
Framework empresarial completo de Google.
- • TypeScript obligatorio
- • Opiniones fuertes: estructura, inyección de dependencias
- • Ideal para aplicaciones grandes y equipos amplios
- • Curva de aprendizaje alta
Svelte
Compila a JavaScript vanilla en tiempo de build.
- • Sin virtual DOM — mejor rendimiento
- • Sintaxis muy cercana a HTML/CSS/JS
- • Menor tamaño de bundle
- • Comunidad más pequeña
Comparativa rápida
| Aspecto | React | Vue | Angular | Svelte |
|---|---|---|---|---|
| Curva de aprendizaje | Media | Baja | Alta | Baja |
| Ofertas laborales | Máximas | Muchas | Enterprise | Menos |
| TypeScript | Opcional | Opcional | Obligatorio | Opcional |
| Rendimiento | Alto | Alto | Medio | Muy alto |
Recomendación
Aprende React primero: mayor demanda laboral, más recursos y una transición suave a React Native para móvil.
¿Por qué usar un framework?
Antes de profundizar en React, conviene ver qué tienen en común estos frameworks y por qué dominan el frontend moderno.
Componentes reutilizables
Encapsulan HTML, CSS y lógica en una sola pieza. Se prueban por separado y se componen para construir la app trozo a trozo.
Manejo de estado
Cada componente gestiona sus propios datos. Cuando el estado cambia, la UI se redibuja sola — sin tocar el DOM a mano.
Reactividad optimizada
El framework calcula el cambio mínimo y solo actualiza ese trozo del DOM. Actualizaciones en tiempo real, sin parpadeos.
Ya no manipulas el DOM a mano
En lugar de document.querySelector(...) y modificar nodos manualmente, describes cómo se ve la UI según el estado y el framework se encarga de sincronizar la pantalla.
Más allá del código: beneficios para el equipo
Adoptar un framework no es solo un asunto técnico — cambia cómo trabaja el equipo y qué herramientas tiene disponibles.
Estándar compartido
Cualquier dev React entiende cualquier proyecto React. Onboarding rápido y un vocabulario común: props, hooks, estado, efectos.
Tooling profesional
Hot reload, DevTools de navegador, linters específicos y librerías de testing. Productividad alta desde el día uno.
Ecosistema enorme
Routing, formularios, fetching, animaciones, gráficos... todo viene resuelto por librerías compatibles, mantenidas y documentadas.
TypeScript de serie
Todos soportan tipado estático. Componentes, props y eventos quedan documentados en el código y el editor te avisa al instante.
SSR y SSG
Next.js, Nuxt o SvelteKit renderizan en servidor para SEO, primer pintado rápido y mejor experiencia en redes lentas.
Multiplataforma
React Native, NativeScript o Capacitor te dejan reutilizar conceptos —y a veces código— en apps móviles y de escritorio.
React — la librería que vamos a usar
De los cuatro frameworks anteriores, Reactes el que vamos a usar en el curso. Veamos por qué y cómo se ven sus piezas fundamentales.
Más demandado
Lidera ofertas laborales frontend desde hace casi una década.
Comunidad enorme
Miles de librerías compatibles, recursos y respuestas a cualquier duda.
React Native
Lo que aprendes aquí te abre la puerta a apps móviles nativas.
Hecho en casa
Esta web del curso —incluidas las slides que estás viendo— está construida con React + TypeScript + Tailwind + DaisyUI. Después de esta clase entenderás cómo está hecha.
Diseñar componentes reutilizables
Un buen componente solo conoce sus props: recibe datos por arriba, expone callbacks hacia arriba y se compone con children para que cada padre decida qué meter dentro.
// Card genérica — un "slot" con childrenfunction Card({ titulo, children }) { return ( <article class="card"> <h3>{titulo}</h3> {children} </article> );}<Card titulo="Aviso"> <p>Cualquier JSX dentro</p> <Boton>Ok</Boton></Card>// useToggle.ts — empaqueta lógicafunction useToggle(inicial = false) { const [v, setV] = useState(inicial); const toggle = () => setV(p => !p); return [v, toggle] as const;}// Cualquier componente lo reutilizafunction Modal() { const [abierto, alternar] = useToggle(); return abierto ? <Dialogo onClose={alternar}/> : <button onClick={alternar}>Abrir</button>;}Tres palancas de reutilización
- • Props: parametrizan datos y callbacks.
- • children: dejas un hueco para que el padre decida el contenido.
- • Custom hooks: empaquetan lógica con estado y la reutilizas en cualquier componente.
📚Material complementario▾
Estado local: useState y useReducer
El estado local vive dentro de un componente. Si dos hijos lo necesitan, súbelo al padre común (lifting state up) y pásalo por props.
// useReducer: estado con muchas transicionestype Accion = | { type: 'add'; texto: string } | { type: 'toggle'; id: number };function reducer(state, accion: Accion) { switch (accion.type) { case 'add': return [...state, ...]; case 'toggle': return state.map(...); }}function ListaTareas() { const [tareas, dispatch] = useReducer(reducer, []); // dispatch({ type: 'add', texto })}useState
Para valores simples e independientes: un input, un toggle, un contador. Devuelve [valor, setter].
useReducer
Cuando el siguiente estado depende del anterior y hay varias acciones posibles. Más predecible y testeable que múltiples useState.
Lifting state up
Si dos hermanos necesitan el mismo dato, vive en el padre común. Datos bajan por props, eventos suben por callbacks.
📚Material complementario▾
Estado global: cuando la prop pasa por demasiados niveles
Cuando un dato (usuario logueado, tema, idioma, carrito...) lo necesitan componentes en ramas distintas, pasarlo por props se vuelve doloroso (prop drilling). Hay tres opciones según el tamaño del problema.
Context + Provider
Built-inLa solución oficial de React. Defines un Context, lo envuelves con <Provider value={...}> y lo lees conuseContext.
Ideal para: tema, idioma, usuario autenticado, valores que cambian poco.
Cuidado: cualquier consumidor re-renderiza al cambiar el valor.
Zustand
LigeroStore mínimo: un hook que devuelve estado y acciones. Sin providers, sin boilerplate. Selectores granulares evitan re-renders innecesarios.
Ideal para: apps pequeñas y medianas, cuando Context se queda corto pero Redux es excesivo.
~3 KB · API minimalista
Redux Toolkit
EnterpriseEstado predecible con actions y reducers. DevTools de tiempo viaje, middleware (sagas, RTK Query) y un patrón muy estándar.
Ideal para: apps grandes con equipos amplios, lógica compleja y necesidad de auditoría de cambios.
Más boilerplate · DevTools potentes
Regla práctica
Empieza con estado local. Si lo necesitan en otros sitios, súbelo al padre. Si cruza muchos niveles, prueba Context. Si la lógica crece, salta a Zustand. Solo cuando el equipo y la app sean grandes, considera Redux Toolkit.
📚Material complementario▾
Optimización: useMemo, useCallback y amigos
React re-renderiza un componente cada vez que su estado o sus props cambian. La mayor parte del tiempo es suficientemente rápido, pero hay hooks pensados para los casos en los que no lo es.
// useMemo: memoiza un valor caroconst ordenadas = useMemo( () => tareas.sort(comparador), [tareas]);// useCallback: memoiza una funciónconst onAgregar = useCallback( (texto) => dispatch({ type: 'add', texto }), [dispatch]);// React.memo: el componente solo re-renderiza// si sus props (por referencia) cambianconst Tarea = React.memo(function Tarea({...}) { // ...});useMemo
Cachea el resultado de un cálculo caro entre renders. Solo recalcula cuando cambian sus dependencias.
useCallback
Cachea la referencia de una función. Útil cuando la pasas a un componente memoizado o como dependencia de otro hook.
React.memo y lazy
React.memo evita re-renders cuando las props no cambian.lazy + Suspense dividen el bundle y cargan partes de la app bajo demanda.
No optimices a ciegas
Mide primero con React DevTools Profiler. Memoizar de más añade código sin beneficio real y a veces empeora el rendimiento.
Siguiente paso
Ya tenemos componentes, estado y optimizaciones. Pero conforme la app crece, JavaScript nos deja indefensos ante errores tontos. Es hora de hablar de TypeScript.
📚Material complementario▾
JavaScript no sabe qué espera tu código
En JavaScript las variables y los parámetros no tienen tipo. Cualquier función acepta cualquier cosa, y los errores aparecen cuando ya es tarde: en producción, frente al usuario.
function calcularPrecio(producto) { return producto.precio * producto.cantidad;}calcularPrecio("hola");// TypeError: cannot read property 'precio'calcularPrecio({ precio: 10 });// NaN (cantidad es undefined)calcularPrecio();// TypeError en producciónErrores típicos sin tipos
- • Llamar una función con un argumento del tipo equivocado
- • Acceder a una propiedad que no existe (typo, renombrado)
- • Olvidar pasar un argumento obligatorio
- • Mezclar números con strings en operaciones
¿Por qué duele tanto?
Estos errores no se detectan al guardar el archivo. Aparecen cuando el usuario navega por la página. Cada bug que llega a producción cuesta tiempo, dinero y confianza.
TypeScript: tipos para JavaScript
TypeScript es JavaScript + tipos estáticos. Anotas los datos que esperan tus funciones y el compilador detecta los errores antes de ejecutar el código —mientras escribes, en el editor.
interface Producto { precio: number; cantidad: number;}function calcularPrecio(p: Producto): number { return p.precio * p.cantidad;}calcularPrecio("hola");// ERROR antes de compilarcalcularPrecio({ precio: 10 });// ERROR: falta cantidadErrores antes de ejecutar
El editor te subraya el problema mientras escribes. Nada llega a producción sin pasar por el compilador.
Autocompletado real
El editor sabe qué propiedades tiene un Producto y te las ofrece. Refactorizar (renombrar, mover) es seguro.
100% compatible con JS
Todo JavaScript válido es TypeScript válido. Puedes adoptarlo archivo por archivo y compila a JavaScript estándar.
Interfaces: la forma de los objetos
interface Usuario { nombre: string; email: string; esAdmin?: boolean; // opcional}function saludar(u: Usuario): string { return `Hola, ${u.nombre}`;}saludar({ nombre: "Ana", email: "ana@ej.com" });Propiedades opcionales
Añade ? después del nombre para que TypeScript no exija esa propiedad.
Interface vs type
Usa interface para describir objetos que podrían extenderse, y type para alias, uniones y literales.
Autocompletado real
Tu editor sugiere propiedades y detecta typos al instante. Menos errores, refactors seguros.
Instalar y arrancar
TypeScript se compila a JavaScript estándar. Tres comandos bastan para empezar:
npm install -g typescripttsc --initcrea tsconfig.json con la configuracióntsc archivo.tsgenera archivo.js listo para ejecutartsc --watchrecompila al guardarMigración gradual
Puedes adoptar TypeScript archivo por archivo. Renombra .js a.ts y empieza a añadir tipos donde más aportan.
Ejemplo: lista de tareas en TypeScript
interface Tarea { id: number; titulo: string; completada: boolean; fechaCreacion: Date; prioridad: "alta" | "media" | "baja";}type FiltroTarea = "todas" | "completadas" | "pendientes";let tareas: Tarea[] = [];let siguienteId = 1;function agregarTarea(titulo: string, prioridad: Tarea["prioridad"] = "media"): Tarea { const nueva: Tarea = { id: siguienteId++, titulo, completada: false, fechaCreacion: new Date(), prioridad }; tareas.push(nueva); return nueva;}function filtrarTareas(filtro: FiltroTarea): Tarea[] { switch (filtro) { case "completadas": return tareas.filter(t => t.completada); case "pendientes": return tareas.filter(t => !t.completada); case "todas": return tareas; }}Demo en vivo — ver errores de TypeScript
Pasa el cursor sobre las líneas en rojo para ver el código de error que reportaría tsc. Pulsa Arreglarpara ver la versión corregida.
interface Libro {
titulo: string;
autor: string;
paginas: number;
disponible: boolean;
}
const miLibro: Libro = { titulo: "Clean Code" };
function calcularTiempoLectura(paginas: number): string {
return paginas * 2;
}
function mostrarLibro(libro: Libro): void {
console.log(libro.isbn);
}
calcularTiempoLectura("trescientos");
interface Libro {
titulo: string;
autor: string;
paginas: number;
disponible: boolean;
}
const miLibro: Libro = {
titulo: "Clean Code",
autor: "Robert C. Martin",
paginas: 464,
disponible: true
};
function calcularTiempoLectura(paginas: number): number {
return paginas * 2;
}
function mostrarLibro(libro: Libro): void {
console.log(libro.titulo);
}
calcularTiempoLectura(300);
Línea
Resumen de la Clase 5
| Concepto | Definición |
|---|---|
| Framework CSS | Estilos predefinidos que aceleran el desarrollo visual |
| Utility-first | Filosofía de Tailwind: clases pequeñas y componibles |
| Bootstrap | Framework CSS de componentes predefinidos (Twitter, 2011) |
| DaisyUI | Plugin de Tailwind con componentes semánticos y temas integrados |
| Componente | Pieza autónoma de interfaz (HTML + CSS + lógica) reutilizable con props |
| Props | Argumentos de entrada que parametrizan un componente |
| React | Librería de componentes reutilizables (Meta, 2013), la más usada del ecosistema |
| JSX | Sintaxis que mezcla HTML y JavaScript dentro de un componente React |
| Hook | Función especial de React (useState, useEffect...) que añade estado o efectos al componente |
| TypeScript | Superset de JavaScript con tipado estático que detecta errores antes de ejecutar |
| Interface | Definición de la forma que debe tener un objeto |
| tsc | Compilador oficial de TypeScript a JavaScript |
📚Material complementario▾
- DocsTailwind CSS — Documentación oficial
- DocsDaisyUI — Componentes para Tailwind
- InteractivoDaisyUI — Galería de temas
- DocsBootstrap — Documentación oficial
- DocsReact — Guía oficial
- DocsVue.js — Guía
- DocsAngular — Docs
- InteractivoSvelte — Tutorial interactivo
- DocsTypeScript — Handbook
- ArtículoState of JS (últimos resultados)
Ejercicio 5.1: Card de perfil con Tailwind
Crea una card de perfil con Tailwind (vía CDN): imagen circular, nombre, puesto, 3 estadísticas (Posts, Seguidores, Siguiendo) y botón "Seguir".
Ana García
Desarrolladora Full-Stack
142
Posts
1.2k
Seguidores
89
Siguiendo
<div class="max-w-sm mx-auto bg-white rounded-xl shadow-lg p-6"> <img class="w-24 h-24 rounded-full mx-auto mb-4" src="..." /> <h2 class="text-xl font-bold">Ana</h2> <p class="text-gray-500 mb-4">...</p> <div class="flex justify-around mb-4"> <div>...stats...</div> </div> <button class="bg-blue-600 text-white px-6 py-2 rounded-full hover:bg-blue-700">Seguir</button></div>Ejercicio 5.2: Comparativa de frameworks
Investiga el ecosistema actual y decide qué framework aprender primero.
Tareas
- ☑ Visita las webs oficiales de React, Vue, Angular y Svelte
- ☑ Busca "ofertas de empleo <framework>" en tu ciudad
- ☑ Revisa la última edición de
stateofjs.com - ☑ Lee un tutorial de 10 minutos de cada uno
- ☑ Escribe un documento corto con tus hallazgos
Entregable
Un markdown de ~300 palabras con:
- • Framework elegido y por qué
- • Nº de ofertas laborales encontradas
- • Popularidad según State of JS
- • Primera impresión de la sintaxis
Ejercicio 5.3: Primeros pasos con TypeScript
Copia el siguiente código en tu editor, instala TypeScript y encuentra los errores tú mismo. Compila con tsc hasta que pase sin avisos.
interface Tarea {
id: number;
titulo: string;
prioridad: "alta" | "media" | "baja";
completada: boolean;
}
const miTarea: Tarea = {
id: 1,
titulo: "Estudiar TypeScript",
prioridad: "urgente",
completada: false
};
function calcularDuracion(horas: number): boolean {
return horas * 60;
}
const tareas: Tarea[] = [];
function buscarTarea(id: number): Tarea | undefined {
return tareas.find(t => t.codigo === id);
}
calcularDuracion("dos");
interface Tarea {
id: number;
titulo: string;
prioridad: "alta" | "media" | "baja";
completada: boolean;
}
const miTarea: Tarea = {
id: 1,
titulo: "Estudiar TypeScript",
prioridad: "alta",
completada: false
};
function calcularDuracion(horas: number): number {
return horas * 60;
}
const tareas: Tarea[] = [];
function buscarTarea(id: number): Tarea | undefined {
return tareas.find(t => t.id === id);
}
calcularDuracion(2);
Ejercicio 5.4: Tienda en TypeScript
Construye un sistema de carrito con tipos: Producto con categoría como union type, ItemCarrito, funciones tipadas para agregar, eliminar, filtrar y aplicar descuento (0–100).
Catálogo
Auriculares Bluetooth
electronica59.90 €Camiseta básica
ropa19.50 €Café de especialidad 250g
alimentos14.00 €Clean Code
libros32.00 €- Sin productos en esta categoría.
Carrito
Añade productos desde el catálogo.
Descuento debe estar entre 0 y 100.
Proyecto: Portafolio con React + TypeScript + Tailwind + DaisyUI
Construye un portafolio personal desde cerousando el stack completo de la clase: Vite + React + TypeScriptpara la lógica y Tailwind + DaisyUI para los estilos y componentes.
Requisitos del proyecto
- • Andamio creado con
npm create vite@latest -- --template react-ts - • Tailwind CSS y DaisyUI instalados y configurados
- • Todos los estilos con utilidades Tailwind / clases DaisyUI
- • Cero
any, todos los componentes con props tipadas - • Mínimo 4 componentes reutilizables (Header, Card, Button, etc.)
- • Responsive en mobile, tablet y desktop
Técnicas que aplicarás
- •
interface Proyectoy array tipado de proyectos - • Composición con
childrenen componentes contenedores - • Estado local con
useState(filtros, modal abierto) - • Toggle de tema con
data-themede DaisyUI - • Componentes DaisyUI:
card,btn,navbar,badge - • Compilación sin errores con
tsc --noEmit
Setup del proyecto en cinco comandos
Vite genera el andamio React + TypeScript, y luego añadimos Tailwind y DaisyUI.
npm create vite@latest mi-portafolio# Selecciona React + TypeScriptcd mi-portafolio && npm installnpm install tailwindcss @tailwindcss/vitenpm install -D daisyui@latestnpm run devvite.config.ts
Importa tailwindcss de @tailwindcss/vite y añádelo al array de plugins junto a react.
src/index.css
@import "tailwindcss"; en la primera línea, y@plugin "daisyui"; debajo para activar los componentes.
Listo
Ya puedes usar class="btn btn-primary",card, navbar... y cualquier utilidad Tailwind.
Criterios de evaluación
Checklist
- ☑ Stack: Vite + React + TypeScript + Tailwind + DaisyUI
- ☑ TypeScript compila sin errores (
tsc --noEmit) - ☑ Props tipadas con
interface, sinany - ☑ Mínimo 4 componentes reutilizables
- ☑ Uso de
useStatepara al menos un estado local - ☑ Estilos con utilidades Tailwind y componentes DaisyUI
- ☑ Responsive en mobile, tablet y desktop
Bonus
- ⭐ Toggle de tema con
data-themede DaisyUI - ⭐ Routing con React Router (Inicio, Proyectos, Contacto)
- ⭐ Custom hook reutilizable (
useTheme,useFiltro...) - ⭐ Animaciones con
transition-* - ⭐ Publicar en Vercel o Netlify
- ⭐ Lighthouse > 90 en accesibilidad
Ya hablas el idioma del frontend moderno
Tailwind, un framework JS y TypeScript son labase del desarrollo web profesional en 2026. En la próxima clase entramos albackend: servidores, APIs y bases de datos.