Fragua Tech

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ónRecomendación
Prototipo rápidoBootstrap
Panel de administraciónTailwind + DaisyUI
Sitio con diseño totalmente únicoTailwind
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.

Definición
// Un componente = una función
function Boton({ texto, color }) {
  return (
    <button class={`btn ${color}`}>
      {texto}
    </button>
  );
}
Uso múltiple
// 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 otros
function 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

ReactLibrería dominante
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>
  );
}
VueProgresivo y accesible
<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

AspectoReactVueAngularSvelte
Curva de aprendizajeMediaBajaAltaBaja
Ofertas laboralesMáximasMuchasEnterpriseMenos
TypeScriptOpcionalOpcionalObligatorioOpcional
RendimientoAltoAltoMedioMuy 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.

Profundizamos

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.

Props + composición con children
// Card genérica — un "slot" con children
function Card({ titulo, children }) {
  return (
    <article class="card">
      <h3>{titulo}</h3>
      {children}
    </article>
  );
}
<Card titulo="Aviso">
  <p>Cualquier JSX dentro</p>
  <Boton>Ok</Boton>
</Card>
Custom hook: lógica reutilizable
// useToggle.ts — empaqueta lógica
function useToggle(inicial = false) {
  const [v, setV] = useState(inicial);
  const toggle = () => setV(p => !p);
  return [v, toggle] as const;
}
// Cualquier componente lo reutiliza
function 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 transiciones
type 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-in

La 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

Ligero

Store 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

Enterprise

Estado 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 caro
const ordenadas = useMemo(
  () => tareas.sort(comparador),
  [tareas]
);
// useCallback: memoiza una función
const onAgregar = useCallback(
  (texto) => dispatch({ type: 'add', texto }),
  [dispatch]
);
// React.memo: el componente solo re-renderiza
// si sus props (por referencia) cambian
const 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
El problema

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.

JavaScript: explota en runtime
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ón

Errores 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.

La solución

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.

El mismo código, ahora seguro
interface Producto {
  precio: number;
  cantidad: number;
}
function calcularPrecio(p: Producto): number {
  return p.precio * p.cantidad;
}
calcularPrecio("hola");
// ERROR antes de compilar
calcularPrecio({ precio: 10 });
// ERROR: falta cantidad

Errores 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 typescript
tsc --init
crea tsconfig.json con la configuración
tsc archivo.ts
genera archivo.js listo para ejecutar
tsc --watch
recompila al guardar

Migració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.

4 errores de TypeScript
          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");
        
Pasa el cursor sobre las líneas marcadas en rojo para ver el error de TypeScript.

Resumen de la Clase 5

ConceptoDefinición
Framework CSSEstilos predefinidos que aceleran el desarrollo visual
Utility-firstFilosofía de Tailwind: clases pequeñas y componibles
BootstrapFramework CSS de componentes predefinidos (Twitter, 2011)
DaisyUIPlugin de Tailwind con componentes semánticos y temas integrados
ComponentePieza autónoma de interfaz (HTML + CSS + lógica) reutilizable con props
PropsArgumentos de entrada que parametrizan un componente
ReactLibrería de componentes reutilizables (Meta, 2013), la más usada del ecosistema
JSXSintaxis que mezcla HTML y JavaScript dentro de un componente React
HookFunción especial de React (useState, useEffect...) que añade estado o efectos al componente
TypeScriptSuperset de JavaScript con tipado estático que detecta errores antes de ejecutar
InterfaceDefinición de la forma que debe tener un objeto
tscCompilador oficial de TypeScript a JavaScript
Material complementario
Básico

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".

Avatar de Ana García

Ana García

Desarrolladora Full-Stack

142

Posts

1.2k

Seguidores

89

Siguiendo

Tema:
<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>
Básico

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
Intermedio

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");
        
Avanzado

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 €

Carrito

Añade productos desde el catálogo.

    Subtotal0.00 €
    Total0.00 €
    🚀

    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 Proyecto y array tipado de proyectos
    • • Composición con children en componentes contenedores
    • • Estado local con useState (filtros, modal abierto)
    • • Toggle de tema con data-theme de 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 + TypeScript
    cd mi-portafolio && npm install
    npm install tailwindcss @tailwindcss/vite
    npm install -D daisyui@latest
    npm run dev

    vite.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, sin any
    • ☑ Mínimo 4 componentes reutilizables
    • ☑ Uso de useState para al menos un estado local
    • ☑ Estilos con utilidades Tailwind y componentes DaisyUI
    • ☑ Responsive en mobile, tablet y desktop

    Bonus

    • ⭐ Toggle de tema con data-theme de 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.

    Fragua Tech — Clase 5