🎯 Objetivo del tema
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.
El alcance, los features, el stack, y los criterios de éxito.
Diagramas de cómo se conectan las partes y qué hace cada una.
Crear el monorepo con /frontend y /backend, configurar scripts, y variables de entorno.
Aplicar todos los temas 3.1-3.6 en una app cohesiva.
API REST con auth JWT para que el usuario guarde sus países favoritos.
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.
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.
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.
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/
EOFEstructura del monorepo y comandos de setup
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
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
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 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
- Setup: crea el monorepo atlas-mundial-pro con /frontend y /backend.
- Frontend: migra tu Atlas Mundial de Tema 3.5 al nuevo monorepo.
- Aplica Atomic Design: organiza componentes en atoms/molecules/organisms/templates/pages.
- Crea Storybook con 10+ componentes documentados.
- Implementa React Router con 5 rutas (/, /pais/:id, /login, /favoritos, /sobre).
- Integra 4 APIs: REST Countries, Open-Meteo, Leaflet, Rick and Morty.
- Backend: crea API REST con auth + favoritos.
- Conecta Supabase: auth + DB para favoritos.
- Tests: implementa 30+ tests con coverage >70%.
- A11y + SEO: pasa 95+ en Lighthouse en las 4 categorías.
- CI/CD: configura GitHub Actions con lint + tests + build + deploy.
- Deploy: Vercel (frontend) + Railway (backend) + Supabase (DB).
- Escribe README profesional con badges, demo, screenshots.
- Publica el repo en GitHub (público).
- Agrega el proyecto a tu CV, LinkedIn, y portafolio.
- Anota en tu cuaderno: 'Lo que aprendí en este curso' en 1 página.
- 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
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%.
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.
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.
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).
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
- Setup: crea monorepo atlas-mundial-pro con /frontend y /backend.
- Frontend: migra Atlas Mundial del Tema 3.5 al monorepo. Aplica Atomic Design.
- Implementa 4 APIs: REST Countries, Open-Meteo, Leaflet, Rick and Morty.
- Routing: /, /pais/:id, /login, /favoritos, /sobre con accesibilidad.
- Auth: integra Supabase Auth con email/password.
- Favoritos: CRUD con backend Express + Supabase DB.
- Storybook: 10+ componentes documentados.
- Tests: 30+ tests con coverage >70% (Vitest + RTL + MSW).
- A11y: WCAG AA, Lighthouse 95+ en las 4 categorías.
- SEO: react-helmet-async, sitemap, Open Graph.
- CI/CD: GitHub Actions con lint + tests + build + deploy.
- Deploy: Vercel (frontend) + Railway (backend) + Supabase (DB).
- README: profesional con badges, demo, screenshots, instalación, tests, deploy.
- Pídele a la IA 3 features adicionales. Implementa 1.
- Verifica el checklist final (10 puntos del bloque 3.10.6).
- Publica en GitHub. Agrega a CV/LinkedIn/portafolio.
- Anota en tu cuaderno: 'Lo que aprendí en este curso' en 1 página.
- 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.