🏆 3.10 · Proyecto final FullStack: Atlas Mundial PRO integrador

⏱ 10h 00min ⚡ 200 XP 🏅 Senior Junior 📖 Frontend Moderno y Proyecto Final
"No es el código que escribes. Es el problema que resuelves. Es el sistema que diseñas. Es la app que podrías mostrar con orgullo en una entrevista."

🎯 Objetivo del tema

Al terminar este tema serás capaz de: Al terminar este tema habrás construido una aplicación FullStack profesional COMPLETA, lista para tu portafolio: Atlas Mundial PRO. Integra TODO lo aprendido en 9 temas: frontend con React + Vite, Atomic Design + Storybook, React Router con accesibilidad, consumo de múltiples APIs públicas, UI/UX profesional, accesibilidad WCAG AA, SEO técnico, testing automatizado con coverage >70%, y CI/CD con deploy automático. La app tiene backend opcional (Node.js + Express + Supabase) para auth y favoritos. Es tu carta de presentación para entrevistas de trabajo como Desarrollador Junior.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

🗺️ Mapa del tema

Llegaste al FINAL del curso. En 35 temas recorriste: HTML, CSS, JS, backend con PHP y Node, bases de datos SQL y NoSQL, React, accesibilidad, SEO, APIs, testing, y CI/CD. Ahora vas a DEMOSTRAR que dominas todo eso construyendo Atlas Mundial PRO: una app FullStack que combina frontend, backend opcional, testing, deploy, y buenas prácticas. Es el proyecto que pondrás en tu CV, en tu portafolio de GitHub, y en tu perfil de LinkedIn. Es la diferencia entre 'sé programar' y 'puedo mostrarte lo que construyo'. En entrevistas junior, este tipo de proyecto vale más que 5 certificaciones.

1. Visión del proyecto: qué vas a construir y por qué

El alcance, los features, el stack, y los criterios de éxito.

2. Arquitectura: frontend, backend opcional, APIs externas

Diagramas de cómo se conectan las partes y qué hace cada una.

3. Setup del proyecto: monorepo, dependencias, scripts

Crear el monorepo con /frontend y /backend, configurar scripts, y variables de entorno.

4. Frontend: React + Vite + Atomic Design + Storybook

Aplicar todos los temas 3.1-3.6 en una app cohesiva.

5. Backend opcional: Node + Express + Supabase para favoritos

API REST con auth JWT para que el usuario guarde sus países favoritos.

6. Testing, CI/CD, deploy y portafolio: cerrar el ciclo

Tests >70%, pipeline en GitHub Actions, deploy, README profesional, demo en vivo.

3.10.1 Visión del proyecto: qué vas a construir y por qué

Atlas Mundial PRO es una app FullStack que permite explorar CUALQUIER país del mundo con datos en tiempo real: bandera, capital, población, idiomas, clima actual, mapa interactivo, y personajes de Rick and Morty originarios de ese país. El usuario puede registrarse, guardar países favoritos, y filtrar por idioma/región. Es una demostración de cómo construir una app moderna con múltiples APIs, auth, persistencia, y UX profesional.

📷 Imagen referencial: Visión de Atlas Mundial PRO: app FullStack con frontend React, backend Node/Express, base de datos Supabase, 4+ APIs externas integradas (REST Countries, Open-Meteo, Leaflet, Rick and Morty), y auth con JWT.

Los 10 features que la app DEBE tener

  • Búsqueda en vivo de países con debounce (mínimo 3 caracteres).
  • Vista detalle de país: bandera, datos básicos, capital, población, idiomas, mapa con Leaflet.
  • Clima actual con Open-Meteo usando las coordenadas del país.
  • Personaje aleatorio de Rick and Morty 'originario' del país (por filtro de origen o especie).
  • Sistema de auth: registro, login, logout con Supabase + JWT.
  • Favoritos: el usuario autenticado puede guardar/eliminar países favoritos.
  • Filtros: por región (América, Europa, Asia, África, Oceanía) y por idioma.
  • Diseño responsive: mobile-first, accesible WCAG AA, 95+ en Lighthouse.
  • Testing: >70% coverage con tests unit + integration.
  • CI/CD: tests + build + deploy automático en cada merge a main.
⭐ Atlas Mundial PRO: tu carta de presentación: El objetivo NO es que la app sea perfecta. El objetivo es que sea DEMOSTRABLE: que un reclutador pueda abrir tu GitHub, ver el código, correrlo localmente, ver los tests pasando, ver el deploy funcionando, y pensar 'este junior sabe lo que hace'. Es la diferencia entre 'hice 10 tutoriales' y 'construí 1 proyecto real'. En entrevistas, los reclutadores miran el portafolio 10x más que las certificaciones.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.10.2 Arquitectura: frontend, backend opcional, APIs externas

La arquitectura de Atlas Mundial PRO sigue el patrón de 3 capas: frontend (lo que ve el usuario), backend (la lógica de negocio y persistencia), y APIs externas (los datos del mundo real). El frontend y el backend se comunican vía HTTP con JSON. El backend se comunica con Supabase (DB + auth) y expone endpoints REST al frontend. Las APIs externas se consumen desde el frontend directamente (son públicas y no necesitan backend) excepto cuando quieres cachear resultados o agregar lógica de negocio.

Diagrama de arquitectura

  • FRONTEND (React + Vite): UI, routing, estado, fetch a APIs externas y al backend propio.
  • BACKEND (Node + Express): API REST propia, auth con JWT, endpoints de favoritos.
  • SUPABASE (BaaS): base de datos PostgreSQL para usuarios y favoritos + auth con JWT.
  • APIs EXTERNAS: REST Countries (países), Open-Meteo (clima), Leaflet+OSM (mapas), Rick and Morty (personajes).
  • DEPLOY: frontend en Vercel, backend en Railway, DB en Supabase (todos tienen plan gratis).
  • CI/CD: GitHub Actions corre tests + build + deploy en cada merge a main.
⭐ Arquitectura moderna: 3 capas + APIs externas: La arquitectura 'frontend + backend ligero + APIs externas' es el PATRÓN dominante de apps modernas. Apps como Spotify (consume su propia API + APIs de artistas), Twitter (consume su API + APIs de partners), y Notion (consume su API + integraciones de terceros) usan este patrón. Es la diferencia entre 'construir todo desde cero' (imposible en 200h) y 'combinar servicios existentes' (realista y escalable). Tu Atlas Mundial PRO es una mini-versión de este patrón.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.10.3 Setup del proyecto: monorepo, dependencias, scripts

El setup del proyecto es FUNDAMENTAL: un monorepo bien organizado le dice al reclutador 'sabe estructurar proyectos'. En este bloque creas la estructura /atlas-mundial-pro con /frontend y /backend, configuras los package.json, los scripts, las variables de entorno, y el .gitignore. Es la base sobre la que construyes todo.

Estructura del monorepo

atlas-mundial-pro/                     # raíz del monorepo
├── .github/
│   └── workflows/
│       └── ci.yml                         # CI/CD pipeline
├── frontend/                              # React + Vite
│   ├── public/
│   ├── src/
│   │   ├── atoms/                         # Button, Input, etc.
│   │   ├── molecules/                     # SearchBar, PaisCard, etc.
│   │   ├── organisms/                     # Header, Footer, etc.
│   │   ├── templates/                     # MainLayout
│   │   ├── pages/                         # Home, DetallePais, Login, Favoritos
│   │   ├── hooks/                         # useFetch, useDebounce, useAuth
│   │   ├── utils/                         # api.js, supabase.js
│   │   ├── App.jsx
│   │   ├── main.jsx
│   │   └── index.css
│   ├── stories/                           # Storybook
│   ├── tests/                             # Vitest + RTL
│   ├── .env.example                       # plantilla de variables
│   ├── .gitignore
│   ├── index.html
│   ├── package.json
│   ├── vite.config.js
│   └── vitest.config.js
├── backend/                               # Node + Express + Supabase
│   ├── src/
│   │   ├── routes/
│   │   │   ├── auth.js                    # registro, login
│   │   │   └── favoritos.js               # CRUD de favoritos
│   │   ├── middleware/
│   │   │   └── auth.js                    # verifica JWT
│   │   ├── db/
│   │   │   └── supabase.js                # cliente de Supabase
│   │   └── server.js                      # entry point
│   ├── .env.example
│   ├── .gitignore
│   └── package.json
├── .gitignore                             # ignora node_modules, .env, dist
├── README.md                              # documentación principal
└── LICENSE                                # MIT

# PASO 1: crear el monorepo
mkdir atlas-mundial-pro && cd atlas-mundial-pro
git init

# PASO 2: crear frontend
npm create vite@latest frontend -- --template react
cd frontend
npm install react-router-dom axios react-leaflet leaflet @supabase/supabase-js
npm install -D vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom msw @storybook/react-vite

# PASO 3: crear backend
mkdir backend && cd backend
npm init -y
npm install express cors @supabase/supabase-js jsonwebtoken bcryptjs dotenv
npm install -D nodemon

# PASO 4: crear .gitignore raíz
cat > .gitignore << EOF
# Dependencies
node_modules/
.pnp
.pnp.js

# Build output
dist/
build/
*.local

# Environment
.env
.env.local
.env.*.local

# Logs
*.log
npm-debug.log*

# IDEs
.vscode/
.idea/
*.swp
.DS_Store

# Coverage
coverage/
.nyc_output/
EOF

Estructura del monorepo y comandos de setup

⭐ Monorepo: estándar para apps fullstack: El monorepo es el ESTÁNDAR para apps fullstack modernas. Proyectos como Babel, React, Next.js, y Vite usan monorepos. Las ventajas: (1) un solo git, una sola versión, una sola rama. (2) puedes compartir código entre frontend y backend (tipos, constantes, utils). (3) los scripts de CI/CD son más simples. (4) el reclutador ve la estructura completa en una sola vista. La alternativa (multi-repo) es para EQUIPOS GRANDES con microservicios; para junior, monorepo es perfecto.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.10.4 Frontend: React + Vite + Atomic Design + Storybook

El frontend de Atlas Mundial PRO integra los temas 3.1 (React), 3.2 (Hooks), 3.3 (Estilos), 3.4 (Router), 3.5 (APIs), 3.6 (UI/UX + Storybook), 3.7 (Accesibilidad + SEO). Es la demostración práctica de que dominas TODOS esos temas. La estructura de carpetas sigue Atomic Design: atoms, molecules, organisms, templates, pages.

Los archivos CLAVE del frontend

// src/utils/supabase.js: cliente de Supabase para el frontend
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

// src/hooks/useAuth.js: hook personalizado para autenticación
import { useState, useEffect } from 'react';
import { supabase } from '../utils/supabase';

export function useAuth() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Obtener sesión inicial
    supabase.auth.getSession().then(({ data: { session } }) => {
      setUser(session?.user ?? null);
      setLoading(false);
    });

    // Escuchar cambios de auth
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_event, session) => {
        setUser(session?.user ?? null);
        setLoading(false);
      }
    );

    return () => subscription.unsubscribe();
  }, []);

  return { user, loading };
}

// src/pages/Home.jsx: página principal con lista de países
import { useState, useEffect } from 'react';
import { useDebounce } from '../hooks/useDebounce';
import { useFetch } from '../hooks/useFetch';
import { PaisCard } from '../molecules/PaisCard';
import { Spinner } from '../atoms/Spinner';

export function Home() {
  const [busqueda, setBusqueda] = useState('');
  const busquedaDebounced = useDebounce(busqueda, 300);
  const [region, setRegion] = useState('all');

  // Fetch a REST Countries con caché y reintento
  const { data: paises, loading, error, refetch } = useFetch(
    `https://restcountries.com/v3.1/${region === 'all' ? 'all' : `region/${region}`}`
  );

  // Filtrar por búsqueda
  const paisesFiltrados = paises?.filter(p =>
    p.name.common.toLowerCase().includes(busquedaDebounced.toLowerCase())
  ) || [];

  return (
    <main>
      <h1>Atlas Mundial PRO</h1>
      <input
        type="search"
        value={busqueda}
        onChange={(e) => setBusqueda(e.target.value)}
        placeholder="Buscar país..."
        aria-label="Buscar país"
      />
      <select value={region} onChange={(e) => setRegion(e.target.value)}>
        <option value="all">Todas las regiones</option>
        <option value="americas">América</option>
        <option value="europe">Europa</option>
        <option value="asia">Asia</option>
        <option value="africa">África</option>
        <option value="oceania">Oceanía</option>
      </select>

      {loading && <Spinner aria-label="Cargando países" />}
      {error && (
        <div role="alert">
          <p>Error al cargar países</p>
          <button onClick={refetch}>Reintentar</button>
        </div>
      )}

      <ul className="paises-grid">
        {paisesFiltrados.map(pais => (
          <li key={pais.cca3}>
            <PaisCard pais={pais} />
          </li>
        ))}
      </ul>
    </main>
  );
}

Frontend: Supabase client, useAuth hook, y página Home

⭐ Frontend: tu examen final visible: El frontend de Atlas Mundial PRO es la DEMOSTRACIÓN de que dominas React. Cada archivo refleja un tema del curso: useAuth (Tema 3.2 hooks), useFetch + useDebounce (Tema 3.5 APIs), PaisCard como molécula (Tema 3.6 Atomic Design), Spinner como átomo, accessible con ARIA (Tema 3.7), y el spinner anuncia loading a lectores de pantalla. Cuando un reclutador abra este código, debe reconocer todos los patrones del curso. Es tu examen final visible.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.10.5 Backend opcional: Node + Express + Supabase para favoritos

El backend es OPCIONAL pero ALTAMENTE recomendado: demuestra que entiendes fullstack, no solo frontend. La lógica es simple: auth con Supabase, CRUD de favoritos (crear, leer, eliminar) con verificación de JWT. El backend se deploya en Railway (plan gratis), Supabase maneja la DB y auth.

Backend: el server.js completo

// backend/src/server.js: entry point del backend
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import { authRouter } from './routes/auth.js';
import { favoritosRouter } from './routes/favoritos.js';
import { verificarToken } from './middleware/auth.js';

dotenv.config();
const app = express();
const PORT = process.env.PORT || 3001;

// Middlewares globales
app.use(cors({ origin: process.env.FRONTEND_URL }));
app.use(express.json());

// Health check (para Railway)
app.get('/health', (req, res) => res.json({ status: 'ok' }));

// Rutas públicas
app.use('/api/auth', authRouter);

// Rutas protegidas (requieren JWT)
app.use('/api/favoritos', verificarToken, favoritosRouter);

app.listen(PORT, () => {
  console.log(`🚀 Backend en http://localhost:${PORT}`);
});

// backend/src/middleware/auth.js: middleware que verifica JWT
import jwt from 'jsonwebtoken';

export function verificarToken(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No autorizado' });
  }
  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;  // { id, email }
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Token inválido' });
  }
}

// backend/src/routes/favoritos.js: CRUD de favoritos
import { Router } from 'express';
import { supabase } from '../db/supabase.js';

export const favoritosRouter = Router();

// GET /api/favoritos - listar favoritos del usuario
favoritosRouter.get('/', async (req, res) => {
  const { data, error } = await supabase
    .from('favoritos')
    .select('*')
    .eq('user_id', req.user.id);
  if (error) return res.status(400).json({ error: error.message });
  res.json(data);
});

// POST /api/favoritos - agregar favorito
favoritosRouter.post('/', async (req, res) => {
  const { codigo_pais, nombre, bandera } = req.body;
  const { data, error } = await supabase
    .from('favoritos')
    .insert([{ user_id: req.user.id, codigo_pais, nombre, bandera }])
    .select();
  if (error) return res.status(400).json({ error: error.message });
  res.status(201).json(data[0]);
});

// DELETE /api/favoritos/:id - eliminar favorito
favoritosRouter.delete('/:id', async (req, res) => {
  const { data, error } = await supabase
    .from('favoritos')
    .delete()
    .eq('id', req.params.id)
    .eq('user_id', req.user.id);  // seguridad: solo tus favoritos
  if (error) return res.status(400).json({ error: error.message });
  res.json({ ok: true });
});

Backend: server.js, middleware auth, CRUD favoritos

⭐ Backend = 1 día extra, empleabilidad x2: El backend con Node + Express + Supabase es la demostración de fullstack real. Al incluirlo en tu portafolio, le dices al reclutador: 'puedo construir una app completa, no solo la parte bonita'. Es el factor que te separa de los juniors que solo saben frontend. Las empresas junior-friendly valoran fullstack: eres más versátil, puedes colaborar con cualquier equipo, y entiendes cómo se conectan las partes. Es 1 día extra de trabajo y multiplica tu empleabilidad por 2.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

3.10.6 Testing, CI/CD, deploy y portafolio: cerrar el ciclo

El último paso es CERRAR EL CICLO: agregar tests, configurar CI/CD, hacer deploy, y escribir un README profesional. Es la diferencia entre 'un proyecto en mi compu' y 'un proyecto en mi portafolio público'. Un reclutador debe poder ver el código, correr los tests, abrir la app desplegada, y leer la documentación en menos de 5 minutos.

El README profesional que enamora reclutadores

# Atlas Mundial PRO 🌍

> Una aplicación FullStack para explorar los países del mundo con datos en tiempo real: bandera, capital, población, idiomas, clima actual, mapa interactivo, y personajes de Rick and Morty.

<p align="center">
  <img src="https://img.shields.io/badge/build-passing-brightgreen" alt="Build">
  <img src="https://img.shields.io/badge/coverage-78%25-brightgreen" alt="Coverage">
  <img src="https://img.shields.io/badge/license-MIT-blue" alt="License">
  <img src="https://img.shields.io/badge/version-1.0.0-blue" alt="Version">
</p>

## ✨ Features

- 🔍 Búsqueda en vivo de 250+ países con debounce
- 🗺️ Vista detalle con mapa interactivo (Leaflet + OpenStreetMap)
- 🌤️ Clima actual en tiempo real (Open-Meteo)
- 👽 Personajes aleatorios de Rick and Morty
- 🔐 Autenticación con email/password (Supabase + JWT)
- ⭐ Sistema de favoritos persistentes
- 📱 Diseño responsive mobile-first
- ♿ Accesibilidad WCAG AA (95+ en Lighthouse)
- ⚡ Performance optimizado (95+ en Lighthouse)
- 🧪 Testing con 78% de coverage
- 🚀 CI/CD con deploy automático

## 🛠️ Stack técnico

**Frontend:** React 19, Vite, React Router, Axios, Leaflet, react-helmet-async
**Backend:** Node.js, Express, Supabase (DB + Auth), JWT
**Testing:** Vitest, React Testing Library, MSW
**CI/CD:** GitHub Actions, Vercel, Railway

## 🚀 Demo en vivo

👉 [https://atlas-mundial-pro.vercel.app](https://atlas-mundial-pro.vercel.app)

## 📦 Instalación local

```bash
# Clonar el repo
git clone https://github.com/tu-usuario/atlas-mundial-pro.git
cd atlas-mundial-pro

# Instalar dependencias
cd frontend && npm install
cd ../backend && npm install
cd ..

# Configurar variables de entorno
cp frontend/.env.example frontend/.env.local
cp backend/.env.example backend/.env
# Editar .env con tus credenciales de Supabase

# Correr en desarrollo (2 terminales)
cd backend && npm run dev    # terminal 1: backend en :3001
cd frontend && npm run dev   # terminal 2: frontend en :5173
```

## 🧪 Tests

```bash
cd frontend
npm test                  # watch mode
npm run test:coverage     # genera reporte de coverage
```

## 🚀 Deploy

El proyecto usa CI/CD con GitHub Actions:
- Cada PR: lint + tests + build
- Cada merge a main: deploy automático a Vercel (frontend) y Railway (backend)

## 📚 Lo que aprendí construyendo este proyecto

[Sección personal donde describes qué aprendiste, qué fue difícil, qué cambiarías]

## 📄 Licencia

MIT - ver [LICENSE](LICENSE)

README profesional con badges, demo, instalación

Checklist final antes de publicar

  • El código compila sin errores: npm run build en frontend y backend.
  • Los tests pasan: npm test en frontend, coverage >70%.
  • El README tiene demo en vivo, capturas, instrucciones claras.
  • El LICENSE es MIT (o el que prefieras).
  • Los issues de GitHub están configurados con templates.
  • Las GitHub Actions corren en verde en cada PR.
  • El deploy funciona: la app en Vercel responde, el backend en Railway responde.
  • Lighthouse en producción: 95+ en las 4 categorías.
  • No hay secrets commiteados (verifica con: git log -p | grep -i 'api_key\|secret' | head).
  • El repo tiene al menos 5 commits descriptivos (feat:, fix:, docs:, test:, ci:).
  • Agregaste el proyecto a tu CV/LinkedIn/portafolio.
⭐ El README es la primera impresión: El README es la PRIMERA IMPRESIÓN. 7 de cada 10 reclutadores junior-friendly miran el README antes que el código. Un README profesional (badges, demo, features, stack, instalación) aumenta la probabilidad de que te contacten 3-5x. No es opcional: es la diferencia entre 'proyecto más' y 'proyecto que destaca'. Invierte 2-3 horas en él. Incluye: badges de CI/coverage, demo en vivo, screenshots, features bullets, stack, instalación paso a paso, tests, deploy, y una sección 'Lo que aprendí' (humaniza tu trabajo).
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

📚 Contenido ampliado

Material adicional, referencias externas verificadas y ejemplos extendidos.

🤖 AI Mission

La IA no construye tu portafolio. Tú construyes tu carrera.

Misión: Construye Atlas Mundial PRO completo: frontend con todos los features, backend opcional con auth, testing >70%, CI/CD, deploy, y README profesional. Comprométete a usarlo como tu proyecto de portafolio. Pídele a la IA: 'Tengo este proyecto FullStack. ¿Qué 3 features adicionales agregarían más valor para una entrevista junior?' Aplica al menos 1. Anota en tu cuaderno: 'Lo que aprendí en este curso en 1 página'.

Pasos sugeridos

  1. Setup: crea el monorepo atlas-mundial-pro con /frontend y /backend.
  2. Frontend: migra tu Atlas Mundial de Tema 3.5 al nuevo monorepo.
  3. Aplica Atomic Design: organiza componentes en atoms/molecules/organisms/templates/pages.
  4. Crea Storybook con 10+ componentes documentados.
  5. Implementa React Router con 5 rutas (/, /pais/:id, /login, /favoritos, /sobre).
  6. Integra 4 APIs: REST Countries, Open-Meteo, Leaflet, Rick and Morty.
  7. Backend: crea API REST con auth + favoritos.
  8. Conecta Supabase: auth + DB para favoritos.
  9. Tests: implementa 30+ tests con coverage >70%.
  10. A11y + SEO: pasa 95+ en Lighthouse en las 4 categorías.
  11. CI/CD: configura GitHub Actions con lint + tests + build + deploy.
  12. Deploy: Vercel (frontend) + Railway (backend) + Supabase (DB).
  13. Escribe README profesional con badges, demo, screenshots.
  14. Publica el repo en GitHub (público).
  15. Agrega el proyecto a tu CV, LinkedIn, y portafolio.
  16. Anota en tu cuaderno: 'Lo que aprendí en este curso' en 1 página.
  17. Haz commit final: 'feat: Atlas Mundial PRO completo, listo para portafolio'.

📓 Entregable: URL pública de Atlas Mundial PRO en Vercel, URL del repo en GitHub con README profesional, captura de GitHub Actions con todos los jobs en verde, reporte de coverage >70%, 1 página de cuaderno con 'Lo que aprendí', y confirmación de agregado a CV/LinkedIn.

🚫 Errores típicos de razonamiento

Error 1: Construir features que nadie usa en vez de pulir las que sí.
Por qué: Es tentador agregar 20 features ('mapa de calor de densidad de población', 'predicción del clima con ML', etc.). Pero una app con 5 features pulidos y 95+ en Lighthouse es MUCHO mejor que una con 20 features a medias y 60 en Lighthouse. Los reclutadores valoran CALIDAD sobre CANTIDAD. La regla: si no puedes explicar el feature en 1 frase, no lo agregues. Si lo agregas, pulirlo 100%.
Error 2: Hardcodear URLs, keys, o strings mágicas en el código.
Por qué: Si pones 'https://api.open-meteo.com/v1/forecast' directamente en el código, tienes 20 strings mágicas dispersas. Si la API cambia de URL, tienes que buscar y reemplazar en 20 lugares. La solución: archivo de constantes (utils/constants.js) y .env para keys. La regla: si un string aparece más de 2 veces, va a constantes. Si es una key/secret, va a .env (nunca commiteado). Es un detalle de senior que los reclutadores notan.
Error 3: No hacer un README profesional (asumir que el código 'se explica solo').
Por qué: El código NUNCA se explica solo. Un reclutador que abre tu repo mira el README en 5 segundos. Si ve 'este es un proyecto de Node' y nada más, cierra la pestaña. Si ve badges, demo en vivo, screenshots, features, stack, instalación en 1 comando, piensa 'este junior sabe lo que hace'. El README es la diferencia entre 'lo miran' y 'lo descartan'. Invierte 2-3 horas. Es la mejor inversión de tiempo en tu portafolio.
Error 4: Olvidar el manejo de errores en producción.
Por qué: En desarrollo todo funciona. En producción algo se rompe: la API se cae, el usuario tiene internet lento, el navegador es Safari y algo no soporta. Si no manejas errores (boundary, retry, mensaje claro al usuario, log a Sentry), tu app muestra 'Error: undefined is not a function' y pierdes al usuario. La regla: SIEMPRE manejar los 3 estados (loading, error, éxito), tener un ErrorBoundary global, y un servicio de monitoring (Sentry gratis).
Error 5: Subir el repo con secrets commiteados o node_modules.
Por qué: Si subes node_modules/ al repo, son 500MB de archivos innecesarios. Si subes un .env con API keys, las key se filtran y pueden hacerte cargos fraudulentos. La solución: .gitignore bien configurado ANTES del primer commit. Verifica: 'git log -p -- .env' debe estar vacío. Y 'ls -la' en el repo remoto no debe tener node_modules. La regla: NUNCA commitees algo que se pueda regenerar (node_modules) o que sea secreto (API keys).

🧪 Laboratorio práctico

Un proyecto en tu portafolio vale más que 5 certificaciones.

Laboratorio: Atlas Mundial PRO: proyecto final FullStack

Objetivo: Construir Atlas Mundial PRO completo: app FullStack con frontend, backend opcional, auth, favoritos, 4 APIs, testing, CI/CD, deploy, y README profesional. El resultado: un proyecto DEMOSTRABLE en tu portafolio de GitHub que demuestra que dominas los 35 temas del curso.

Pasos

  1. Setup: crea monorepo atlas-mundial-pro con /frontend y /backend.
  2. Frontend: migra Atlas Mundial del Tema 3.5 al monorepo. Aplica Atomic Design.
  3. Implementa 4 APIs: REST Countries, Open-Meteo, Leaflet, Rick and Morty.
  4. Routing: /, /pais/:id, /login, /favoritos, /sobre con accesibilidad.
  5. Auth: integra Supabase Auth con email/password.
  6. Favoritos: CRUD con backend Express + Supabase DB.
  7. Storybook: 10+ componentes documentados.
  8. Tests: 30+ tests con coverage >70% (Vitest + RTL + MSW).
  9. A11y: WCAG AA, Lighthouse 95+ en las 4 categorías.
  10. SEO: react-helmet-async, sitemap, Open Graph.
  11. CI/CD: GitHub Actions con lint + tests + build + deploy.
  12. Deploy: Vercel (frontend) + Railway (backend) + Supabase (DB).
  13. README: profesional con badges, demo, screenshots, instalación, tests, deploy.
  14. Pídele a la IA 3 features adicionales. Implementa 1.
  15. Verifica el checklist final (10 puntos del bloque 3.10.6).
  16. Publica en GitHub. Agrega a CV/LinkedIn/portafolio.
  17. Anota en tu cuaderno: 'Lo que aprendí en este curso' en 1 página.
  18. Commit final: 'feat: Atlas Mundial PRO completo, listo para portafolio'.

📓 Entregable: URL del repo en GitHub con README profesional, URL del deploy en Vercel funcionando, captura de GitHub Actions con todos los jobs en verde, reporte de coverage >70%, captura de Lighthouse 95+ en 4 categorías, 1 página de cuaderno con 'Lo que aprendí', y URL del proyecto agregado a CV/LinkedIn.

📓 Tu cuaderno: Anota pseudocódigo, diagramas, errores que encontraste y respuestas a "explica sin código". La escritura manual refuerza tu razonamiento. Tu profesor puede pedirte que subas fotos de páginas específicas.