Construí una aplicación con IA: frontend, API y base de datos
Usá tu copiloto de IA para diseñar, generar, revisar y mejorar un juego web completo: frontend con nginx, API en Node.js que consume PokeAPI y Valkey para la caché, las partidas y el ranking.

Objetivo del laboratorio
Vas a construir "¿Quién es ese Pokémon?", el juego clásico de adivinar un Pokémon por su silueta. No vas a escribir el código a mano: lo vas a dirigir. Diseñás con tu copiloto de IA, le pasás contratos claros, revisás lo que genera y lo verificás con una prueba automática.

- web: nginx sin privilegios. Sirve el frontend y reenvía
/apia la API, así todo sale de un solo origen. - api: Node.js con Express. Tiene la lógica del juego, consulta PokeAPI y nunca revela la respuesta antes de tiempo.
- valkey: guarda la caché de PokeAPI, las partidas en curso y el ranking.
Todo el código lo genera tu copiloto de IA con los prompts de esta guía. Si en algún paso te trabás, al final tenés una solución de referencia para comparar o copiar la pieza que falte.
Antes de empezar
Todos los comandos se ejecutan en docker-01, como el usuario laborant. La máquina tiene Node 24 para que valides rápido el código que genera tu copiloto de IA; la aplicación, igual, corre en contenedores. Si node no aparece, esperá unos segundos y abrí una terminal nueva. Tres herramientas del playground te van a acompañar:
- Terminales. Abrí una segunda pestaña con el botón +: una para los logs y otra para los comandos.
- IDE. La pestaña IDE es un editor en el navegador: ahí guardás el código que genera tu copiloto de IA.
- Exponer puertos. Para abrir el juego en tu navegador: menú ⋮ → Expose HTTP port → puerto
8080→ Expose, y abrí la URL que aparece.

En este laboratorio la IA trabaja como un copiloto: diseña, genera y revisa el código, y vos tomás las decisiones. Usá el asistente que prefieras (ChatGPT, Claude, Gemini, Copilot o Kiro) y seguí siempre el mismo ciclo: pedir con un contrato claro, revisar lo que genera y probar con un comando. Nunca pegues secretos en un prompt.
Paso 1 · Ver la versión terminada (opcional)
Antes de construir, podés levantar la solución completa para ver a dónde vas a llegar:
git clone https://github.com/roxsross/roxs-pokedex-ops.git ~/roxs-pokedex-ops
cd ~/roxs-pokedex-ops
docker compose up -d --build
docker compose ps
Deberías ver: web, api y valkey en estado (healthy). Exponé el puerto 8080 y jugá una partida: probá la pista con la tecla P, elegí otra generación y recargá la página a mitad de partida.

Después, dejá que un bot juegue contra la API:
bash scripts/probar-api.sh roxs
Deberías ver: 10 rondas y el mensaje ✅ La API pasó todas las pruebas. Esa es la meta: al final del laboratorio, la API que construyas con tu copiloto de IA tiene que pasar la misma prueba.
Apagá la versión terminada y borrá sus datos antes de seguir, así empezás de cero y liberás los puertos:
docker compose down -v
El repositorio queda en ~/roxs-pokedex-ops: si más adelante te trabás, lo vas a usar como solución de referencia.
Paso 2 · Preparar el proyecto
Creá la carpeta del proyecto y descargá la prueba automática de la API:
mkdir -p ~/mi-pokedex/api ~/mi-pokedex/web ~/mi-pokedex/scripts
cd ~/mi-pokedex
curl -fsSL -o scripts/probar-api.sh \
https://raw.githubusercontent.com/roxsross/roxs-pokedex-ops/master/scripts/probar-api.sh
ls -R
Corré también cd ~/mi-pokedex en la otra terminal.
probar-api.sh es la meta del laboratorio: juega una partida completa contra tu API y verifica el contrato, la seguridad y la concurrencia. Al final, tu API la tiene que pasar.
Paso 3 · Diseñar la arquitectura
El error más común al construir con tu copiloto de IA es pedir código de entrada: sin un diseño, el modelo decide por vos. Empezá pidiendo solo la arquitectura.
🤖 Prompt · Diseñar la arquitectura
Actuá como arquitecto/a de software. Necesito diseñar un juego web
"¿Quién es ese Pokémon?" para un laboratorio de contenedores.
Requisitos funcionales:
- La persona ingresa su nombre y juega 10 rondas.
- En cada ronda ve la silueta de un Pokémon de la primera generación y elige
entre 4 nombres. Al responder se revela la imagen y sus tipos.
- Se guarda un ranking con el mejor puntaje de cada jugador/a y un historial
de las últimas partidas.
- Los datos de los Pokémon vienen de PokeAPI (https://pokeapi.co).
Requisitos no funcionales:
- Frontend y backend separados, cada uno en su contenedor.
- Respetar la política de uso justo de PokeAPI (cachear los recursos).
- La respuesta correcta nunca debe llegar al navegador antes de responder.
- Las partidas abandonadas no deben acumularse para siempre.
- Todo tiene que levantarse con Docker Compose.
Proponé: los componentes y su responsabilidad, qué base de datos usarías y por
qué, el modelo de datos, y las rutas de la API. Si evaluás alternativas
(por ejemplo, PostgreSQL frente a Valkey), compará ventajas y desventajas en una tabla.
No escribas código todavía.
Tres decisiones que vale la pena buscar en la respuesta:
- PokeAPI la consulta la API, no el navegador. Así se puede cachear y la respuesta correcta queda en el servidor.
- Las partidas expiran solas. Una partida abandonada no tiene que quedar guardada para siempre.
- Valkey frente a PostgreSQL. Para este juego gana Valkey: la caché, las partidas con expiración y el ranking ordenado son estructuras que ya trae (textos con TTL, hashes y sorted sets). Con consultas complejas o reportes, PostgreSQL sería mejor opción.
La propuesta no tiene que ser idéntica. Pero desde el próximo paso vas a usar un contrato fijo, para que tu código pase la prueba automática.
Paso 4 · Generar la API
La API es la pieza central. Su contrato define rutas, campos, reglas y claves de Valkey con tanto detalle que cualquier implementación que lo cumpla funciona con el resto del juego.
🤖 Prompt · Generar la API
Contexto: API para el juego "¿Quién es ese Pokémon?". Node.js 24, CommonJS,
Express 5 y la librería oficial "redis" (node-redis v5) para conectarse a Valkey.
Los datos de los Pokémon vienen de PokeAPI (https://pokeapi.co/api/v2).
Contrato (respetá nombres de rutas, campos y claves exactamente):
- GET /health: PING a Valkey. Responde el texto "ok", o 503.
- GET /api/info: { version (de package.json), partidas (contador stats:partidas) }.
- POST /api/partidas { jugador } (máx. 20 caracteres, obligatorio o 400):
crea el hash partida:{uuid} con TTL de 1 hora e incrementa stats:partidas.
Responde 201 con { id, jugador, total: 10 }.
- GET /api/partidas/:id/ronda: elige un Pokémon al azar entre 1 y 151 que no se
haya usado en la partida, más 3 nombres distintos como distractores, y mezcla
las 4 opciones. Guarda la ronda pendiente en el hash. Responde
{ ronda, total, imagen, opciones }. Si hay una ronda sin responder, devuelve
la misma. NUNCA incluye el nombre correcto por separado.
- POST /api/partidas/:id/respuesta { opcion }: 400 si la opción no es de la
ronda; 409 si no hay ronda pendiente. Acierto: 100 puntos + 20 por cada
acierto consecutivo previo. Responde { correcta, puntos, pokemon: { id, nombre,
tipos: [{ clave, nombre en español }], imagen, altura, peso }, puntaje, racha,
aciertos, ronda, total, terminada }.
Al terminar la ronda 10: guarda en el sorted set "ranking" solo si supera el
récord del jugador, y agrega un resumen a la lista "historial" (máximo 10).
- GET /api/ranking: top 10 del sorted set, [{ jugador, puntaje }].
- GET /api/historial: la lista "historial", [{ jugador, puntaje, aciertos, total, fecha }].
- Partida inexistente: 404.
PokeAPI y caché:
- Nombres: GET /pokemon?limit=151, cacheado en "pokeapi:lista:151".
- Detalle: GET /pokemon/{id}, cacheado en "pokeapi:pokemon:{id}".
Imagen: sprites.other["official-artwork"].front_default.
- Caché con TTL de 24 horas (patrón cache-aside) y timeout de 5 segundos por consulta.
- Nombres legibles: "mr-mime" → "Mr. Mime", "nidoran-f" → "Nidoran♀",
"farfetchd" → "Farfetch'd"; el resto con mayúscula inicial.
- Si PokeAPI falla, la API responde 502 con un mensaje claro.
Configuración y resiliencia:
- PORT (3000), VALKEY_URL (redis://localhost:6379), POKEAPI_URL.
- Listener de "error" en el cliente, disableOfflineQueue: true, y 503 si el
cliente no está listo. La app arranca aunque Valkey no esté disponible.
- Manejo de errores centralizado en un middleware de Express.
Restricciones: solo express y redis. Separá el código en estos módulos, todos
en la raíz de api/: valkey.js (conexión), pokeapi.js (acceso a PokeAPI con
caché), juego.js (lógica del juego) y server.js (rutas HTTP y arranque).
Salida: api/package.json, api/valkey.js, api/pokeapi.js, api/juego.js,
api/server.js, api/Dockerfile (node:24-alpine, usuario node, CMD con server.js,
HEALTHCHECK contra /health con wget) y api/.dockerignore.
Formato: un bloque de código por archivo, con la ruta como título justo antes
del bloque (por ejemplo: ### api/server.js). Nunca pongas la ruta como
comentario dentro del archivo: en JSON y en el Dockerfile rompe el build.
Sin explicaciones entre los archivos.
Guardá los archivos en ~/mi-pokedex/api/. Antes de seguir, fijate en tres cosas:
- Que la respuesta de la ronda no incluya el nombre correcto.
- Que el
CMDdel Dockerfile arranque el archivo que tu copiloto de IA realmente creó. - Que ningún archivo empiece con un comentario como
// package.json. En JSON y en el Dockerfile eso rompe el build.
Antes de construir la imagen, validá lo que generó tu copiloto de IA y creá el lockfile:
cd ~/mi-pokedex/api
node -e "require('./package.json')" && echo "package.json válido"
for f in $(find . -name '*.js' -not -path './node_modules/*'); do node --check "$f" || echo "Error de sintaxis en $f"; done
npm install --package-lock-only
cd ~/mi-pokedex
Con el package-lock.json, el build instala exactamente las mismas versiones cada vez. Si algo falla acá, pasale el error a tu copiloto de IA: es mucho más rápido que descubrirlo en docker compose build.
Ahora pedile el compose.yaml que une las piezas:
🤖 Prompt · Generar el compose.yaml
Escribí un compose.yaml con nombre de proyecto "pokedex" y tres servicios:
- web: se construye desde ./web, imagen "pokedex-web". Adentro corre nginx sin
privilegios, que escucha en el 8080 (no en el 80): publicalo como "8080:8080".
- api: se construye desde ./api, imagen "pokedex-api", con las variables
VALKEY_URL=redis://valkey:6379 y POKEAPI_URL=https://pokeapi.co/api/v2.
Publica el 3000 solo en 127.0.0.1, para probarla con curl desde la máquina.
- valkey: imagen valkey/valkey:8-alpine con persistencia AOF, datos en un
volumen nombrado "valkey-data" y healthcheck con "valkey-cli ping".
Requisitos:
- web arranca cuando api está healthy, y api cuando valkey está healthy.
- Si un contenedor se cae, se reinicia solo, salvo que lo detenga manualmente.
- Valkey no publica ningún puerto.
- Especificación actual de Compose (sin la clave "version").
Devolveme solo el archivo, sin comentarios con su nombre.
Guardalo como ~/mi-pokedex/compose.yaml y levantá la API con Valkey:
docker compose up -d --build api valkey
curl -s localhost:3000/health ; echo
Deberías ver: ok. Probá una ronda a mano:
ID=$(curl -s -X POST localhost:3000/api/partidas -H 'Content-Type: application/json' \
-d '{"jugador":"yo"}' | sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -s localhost:3000/api/partidas/$ID/ronda ; echo
Deberías ver: una ronda con imagen y cuatro opciones. La prueba completa todavía no va a pasar: también verifica las mejoras de los pasos 6 y 7.
Si algo falla, mirá docker compose logs api y pasale el error a tu copiloto de IA.
Paso 5 · Generar el frontend
El frontend solo conoce las rutas de la API. Como nginx reenvía /api, todas las llamadas usan rutas relativas.
🤖 Prompt · Generar el frontend y su servidor web
Contexto: frontend del juego "¿Quién es ese Pokémon?". HTML, CSS y JavaScript
sin frameworks ni librerías externas. Lo sirve nginx, que reenvía /api y /health
a la API, así que todas las llamadas usan rutas relativas.
API disponible:
- POST /api/partidas { jugador } → { id, jugador, total }
- GET /api/partidas/:id/ronda → { ronda, total, imagen, opciones }
- POST /api/partidas/:id/respuesta { opcion } → { correcta, puntos, pokemon:
{ nombre, tipos: [{ clave, nombre }], imagen }, puntaje, racha, aciertos,
ronda, total, terminada }
- GET /api/ranking → [{ jugador, puntaje }]
- GET /api/historial → [{ jugador, puntaje, aciertos, total, fecha }]
- GET /health → "ok"
Pantallas:
1. Inicio: título "¿Quién es ese Pokémon?", campo de nombre, botón Jugar,
y dos tableros: ranking y últimas partidas.
2. Juego: marcador (jugador, ronda, puntaje, racha), barra de progreso, la
imagen como silueta negra (CSS filter: brightness(0)) sobre un fondo de rayos
animado, y 4 botones de opción. Al responder: revelar la imagen con una
transición, marcar en verde la correcta y en rojo la elegida si falló,
mostrar el nombre y los tipos con sus colores, y un botón Siguiente.
Atajos de teclado: 1 a 4 para responder.
3. Fin: puntaje grande, aciertos, un mensaje según el resultado y un botón
para volver a jugar.
Además, un indicador de salud en la barra superior que consulte /health.
Requisitos:
- Mostrá todo texto que venga de la API con textContent, nunca con innerHTML.
- Estilo: modo oscuro, acentos rojo y amarillo, responsive.
- Mostrá los errores de la API en pantalla.
Servidor web:
- nginx.conf: escucha en el 8080, sirve los archivos estáticos y reenvía
/api/ y /health a http://api:3000. Usá el DNS de Docker (resolver 127.0.0.11)
y una variable en proxy_pass, para que nginx siga encontrando a la API si su
contenedor se recrea.
- Dockerfile: imagen nginxinc/nginx-unprivileged:1.27-alpine y HEALTHCHECK con
wget contra http://127.0.0.1:8080/ (no localhost: resuelve primero a IPv6 y
nginx escucha en IPv4).
Salida: web/index.html, web/styles.css, web/app.js, web/nginx.conf y
web/Dockerfile.
Formato: un bloque de código por archivo, con la ruta como título justo antes
del bloque (por ejemplo: ### web/index.html). Nunca pongas la ruta como
comentario dentro del archivo: en JSON y en el Dockerfile rompe el build.
Sin explicaciones entre los archivos.
Guardá los archivos en ~/mi-pokedex/web/ y levantá todo:
docker compose up -d --build
docker compose ps
Deberías ver: web, api y valkey en estado (healthy). Exponé el puerto 8080 y jugá una partida entera.
Una prueba de seguridad rápida: anotate con el nombre <b>hola</b>. Al terminar, en el ranking tiene que aparecer tal cual, con las etiquetas. Si aparece "hola" en negrita, el frontend usa innerHTML y cualquiera podría inyectar HTML en la página: pedile a tu copiloto de IA que lo corrija.
Paso 6 · Revisar y corregir
Que funcione no significa que esté bien hecho. Pedile a tu copiloto de IA solo el diagnóstico:
🤖 Prompt · Revisar el código
Actuá como revisor/a de código con foco en seguridad y operación.
Revisá esta API y este frontend:
[pegá los archivos]
Evaluá SOLO estos puntos y respondé en una tabla con: hallazgo, severidad
(alta/media/baja), archivo y línea, y cómo lo verifico con un comando o prueba.
1. ¿La respuesta correcta puede llegar al navegador antes de responder?
2. ¿Se valida la entrada (jugador, opción, id de partida)?
3. ¿Hay riesgo de inyección de HTML en el frontend?
4. ¿Qué pasa si PokeAPI está caída o tarda? ¿Y si Valkey no está?
5. ¿Se respeta el uso justo de PokeAPI (caché)?
6. ¿Las claves de Valkey tienen la expiración adecuada?
7. ¿Hay condiciones de carrera (por ejemplo, responder dos veces a la vez)?
No reescribas el código: solo el diagnóstico.
Una buena revisión tiene que encontrar estos dos problemas. Si tu copiloto de IA no los menciona, preguntale por cada uno:
| Problema | Por qué pasa |
|---|---|
| La imagen revela la respuesta. | La URL de PokeAPI termina con el número del Pokémon: .../official-artwork/25.png es Pikachu. |
| Responder dos veces a la vez suma doble. | Leer el estado, calcular y guardar no es una operación atómica. |
Ahora pedile que los corrija:
🤖 Prompt · Corregir los dos problemas
Corregí estos dos problemas en la API, sin cambiar las demás rutas ni sus
campos y sin agregar dependencias:
1. La imagen revela la respuesta. En GET /api/partidas/:id/ronda, el campo
imagen tiene que ser una ruta de la propia API:
/api/partidas/:id/imagen?ronda=<número de ronda>.
Agregá GET /api/partidas/:id/imagen, que devuelve la imagen de la ronda
pendiente con su Content-Type (image/png). La API la descarga de PokeAPI una
sola vez y la guarda en Valkey en "pokeapi:imagen:{id}" (en base64, TTL 24 h).
Sin ronda pendiente: 409.
2. Responder dos veces a la vez suma doble. La escritura de la respuesta tiene
que ser atómica: usá un script Lua (EVAL) que actualice el hash de la partida
solo si el campo pokemonId sigue siendo el de la ronda pendiente. El segundo
pedido recibe 409.
Devolveme solo los archivos modificados y, aparte, la lista de cambios.
Formato: un bloque de código por archivo, con la ruta como título justo antes
del bloque (por ejemplo: ### api/server.js). Nunca pongas la ruta como
comentario dentro del archivo: en JSON y en el Dockerfile rompe el build.
Reconstruí y verificá la imagen:
docker compose up -d --build
ID=$(curl -s -X POST localhost:3000/api/partidas -H 'Content-Type: application/json' \
-d '{"jugador":"yo"}' | sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -s localhost:3000/api/partidas/$ID/ronda ; echo
Deberías ver: un campo imagen que empieza con /api/partidas/. En el navegador, la silueta se sigue viendo igual.
Paso 7 · Agregar funcionalidades
Cada funcionalidad nueva se pide con cambio mínimo: sin tocar lo que ya funciona. Usá este prompt una vez por funcionalidad, reemplazando la última parte por una de las especificaciones de abajo:
🤖 Prompt · Agregar una funcionalidad con cambio mínimo
Este es el código actual de la API y del frontend:
[pegá los archivos involucrados]
Restricciones:
- No modifiques el comportamiento de las rutas existentes ni sus campos.
- No agregues dependencias.
- La respuesta correcta no puede llegar al navegador antes de responder.
Devolveme solo los archivos modificados y, aparte, la lista de cambios.
Formato: un bloque de código por archivo, con la ruta como título justo antes
del bloque (por ejemplo: ### api/server.js). Nunca pongas la ruta como
comentario dentro del archivo: en JSON y en el Dockerfile rompe el build.
Quiero agregar:
[pegá acá una de las especificaciones]
Especificación 1 · Pista
Una pista que muestra los tipos del Pokémon antes de responder.
- POST /api/partidas/:id/pista → { tipos, costo: 30 }. Sin ronda pendiente: 409.
- Marca la ronda como "con pista" en el hash; pedirla otra vez no cobra dos veces.
- Si se acierta con pista: 100 + 20 por racha − 30. Si se falla, no descuenta nada.
- POST /respuesta suma el campo pista (true o false).
- Frontend: botón "💡 Pista" y tecla P.
Especificación 2 · Elegir generación
Elegir la generación de Pokémon al crear la partida.
- GET /api/generaciones → [{ generacion, region, desde, hasta }], con:
0 Todas 1-1025, 1 Kanto 1-151, 2 Johto 152-251, 3 Hoenn 252-386,
4 Sinnoh 387-493, 5 Teselia 494-649, 6 Kalos 650-721, 7 Alola 722-809,
8 Galar 810-905, 9 Paldea 906-1025.
- POST /api/partidas acepta "generacion" opcional (por defecto 1). Fuera de 0 a 9: 400.
La respuesta suma el campo generacion.
- Los nombres salen de GET /pokemon-species?offset=<desde-1>&limit=<cantidad>,
cacheados en "pokeapi:lista:gen{n}".
- El historial guarda la generación de cada partida.
- Frontend: un selector de generación en la pantalla de inicio.
Especificación 3 · Resumen final
Un resumen con los 10 Pokémon de la partida.
- Cada respuesta agrega al hash de la partida un elemento a "resumen" (lista JSON):
{ id, nombre, imagen, correcta, puntos, pista }.
- Frontend: en la pantalla final, una grilla con los 10 Pokémon, marcando
aciertos y errores.
Especificación 4 · Continuar la partida al recargar
Poder retomar una partida después de recargar la página.
- GET /api/partidas/:id → { id, jugador, estado, generacion, ronda, total,
puntaje, racha, aciertos, pendiente, resumen }, en ese orden, con resumen
como último campo. estado vale "jugando" o "terminada", y pendiente indica
si hay una ronda sin responder. No incluye el Pokémon de la ronda pendiente.
- Frontend: guarda el id de la partida en localStorage y, al cargar la página,
ofrece continuarla si sigue en curso.
Después de cada cambio, reconstruí con docker compose up -d --build y jugá una partida para ver que nada se rompió.
Con las cuatro funcionalidades, corré la prueba completa, directo contra la API y pasando por nginx:
bash scripts/probar-api.sh yo
bash scripts/probar-api.sh yo http://localhost:8080 9
Deberías ver: ✅ La API pasó todas las pruebas las dos veces. Si falla, la última línea te dice qué parte del contrato no se cumple: pasásela a tu copiloto de IA tal cual.

Si te trabás: la solución de referencia
El juego completo, con todas las funcionalidades de esta guía, está en roxsross/roxs-pokedex-ops. Usalo para comparar tu código o para copiar la pieza que no sale:
git clone https://github.com/roxsross/roxs-pokedex-ops.git ~/roxs-pokedex-ops # si no lo clonaste en el Paso 1
diff -ru ~/roxs-pokedex-ops/api ~/mi-pokedex/api | head -40 # comparar
cp ~/roxs-pokedex-ops/api/juego.js ~/mi-pokedex/api/ # copiar un archivo
Si algo falla
| Síntoma | Qué hacer |
|---|---|
port is already allocated | Quedó corriendo la versión terminada del Paso 1: cd ~/roxs-pokedex-ops && docker compose down -v. |
503 Valkey no disponible | docker compose ps y docker compose logs valkey. |
502 No se pudo consultar PokeAPI | Probá la conexión con curl -sI https://pokeapi.co. |
npm error code EJSONPARSE al construir | Tu copiloto de IA dejó un comentario en la primera línea del package.json (// package.json). Borralo con sed -i '1{/^\/\//d}' api/package.json: JSON no admite comentarios. |
node: command not found | La terminal se abrió antes de que terminara la instalación: abrí una nueva o corré source ~/.nvm/nvm.sh. |
Cannot find module al arrancar la API | El CMD del Dockerfile apunta a un archivo que no existe, o falta una dependencia en package.json. |
El puerto 8080 no responde (Connection reset o Empty reply) | Revisá ports del servicio web en compose.yaml: tiene que ser "8080:8080". Con "8080:80" no hay nadie escuchando adentro, porque nginx sin privilegios usa el 8080. |
| El juego carga pero no aparece el ranking | nginx no llega a la API: docker compose logs web. |
| Los cambios no se ven | Reconstruí con docker compose up -d --build. |
probar-api.sh falla | La última línea dice qué parte del contrato no se cumple. Pasásela a tu copiloto de IA junto con el archivo involucrado. |
Limpieza
cd ~/mi-pokedex
docker compose down -v --rmi local
Cierre
Construiste una aplicación de tres servicios sin escribir el código a mano: diseñaste con tu copiloto de IA, le diste contratos claros, revisaste lo que generó y corregiste dos problemas reales que una prueba automática confirma. Ese es el cambio de fondo al trabajar con un copiloto de IA: el trabajo pasa de escribir código a especificarlo y verificarlo.
Datos e imágenes de PokeAPI. Pokémon y sus nombres son marcas registradas de Nintendo, Creatures Inc. y GAME FREAK Inc.; este es un proyecto educativo sin fines comerciales.
Hecho por Roxs 🔥 · Build with Fire
About the Author
More tutorials you might like

How Servers Work: A Hands-On Introduction to TCP Sockets
Learn how servers actually work by building a tiny TCP server and client from scratch. A hands-on introduction to sockets, TCP, and the network programming model every backend, DevOps, and platform engineer should go through at least once.

Build a Container from Scratch in Go (Liz Rice GOTO 2018)
Follow along with Liz Rice's classic GOTO 2018 presentation and build your own container runtime in under 100 lines of Go using Linux namespaces, chroot, and cgroups.

Using Go for Systems Programming
Discover how Go functions under the hood as a modern systems programming language. Learn how Go makes system calls directly, resulting in self-contained binaries that have no libc dependencies.

Linux Processes: From a Program to a Process
Explore what a program is, when it actually becomes a process and how the Linux scheduler manages process execution.
Learn by doing, not just by reading or watching
Sign up for a free account to start a VM playground right on this page, track your progress, and get notified about new learning materials.