7 modelos gratis de opencode, un solo prompt: qué entregó realmente cada uno
opencode trae una tanda de modelos gratuitos y la pregunta obvia es cuál sirve. No encontré una comparativa que me convenciera, así que hice la mía: un prompt, siete modelos, cero ayudas. Lo que sigue es la bitácora de esa mañana.
Adelanto el resultado que no esperaba: el fallo más grave no fue de diseño ni de código. Fue algo que ningún review de código habría detectado, y para verlo tuve que hacer peticiones HTTP.
Las reglas: todo vanilla
Esto es importante porque define qué mide el experimento y qué no. La prueba fue deliberadamente cruda:
- Sin skills. Ninguna instrucción cargada.
- Sin MCPs. Ningún servidor de contexto conectado.
- Sin spec-driven development. Nada de documento de especificación previo, ni plan, ni fases.
- Sin técnicas de desarrollo agéntico. Sin chain-of-thought forzado, sin auto-crítica, sin iteración, sin "revisa tu trabajo".
- Un solo turno. Pegué el prompt, esperé, y lo que salió es lo que evalué. Sin correcciones ni segundas oportunidades.
Esto no mide el techo de cada modelo. Un buen andamiaje agéntico habría corregido la mitad de los problemas que encontré. Lo que mide es el piso: qué te entrega el modelo cuando le pides algo como se lo pedirías a un colega, sin ceremonia. Y para decidir cuál de los gratuitos vale la pena, el piso es justo lo que quieres saber.
El prompt, literal
Crea una landing page para promocionar una Escuela de música en Soacha, Cundinamarca llamada Javastudios. Esta debe cumplir con las siguiente características:
- Usar colores azules
- Tener un diseño minimalista muy atractivo
- tener al menos una leve animación
- tener un llamado a la acción que dirija a whatsapp
- Tener navegación y footer
- Tener imágenes de Unsplash
Seis requisitos verificables, un negocio local real y suficientemente específico como para que el modelo no pueda salir del piloto automático. Sin más contexto: ni teléfono, ni precios, ni años de trayectoria, ni catálogo de cursos. Retén ese detalle, porque termina siendo el centro del artículo.
Los contendientes
| Modelo | Tiempo | Notas de ejecución |
|---|---|---|
| DeepSeek V4 Flash | 42s | Sin fricción |
| MiMo v2.5 | 1m 53s |
Con default no encontraba el provider; hubo
que forzar variant: medium
|
| Big Pickle | 2m 05s | Escribió en una subcarpeta propia |
| Ling 3.0 Flash | 2m 17s | Sin fricción |
| North Mini Code | 4m 17s | Sin fricción |
| Laguna S 2.1 | 20m 48s* | *Casi todo fueron esperas por rate limit |
| Nemotron 3 Ultra | — |
Streaming response failed en todos los
intentos
|
Empecemos por el que ni siquiera llegó a la pista.
Nemotron 3 Ultra: el que anunció y no entregó
El único "Ultra" de la tanda y el único que no produjo una sola
línea. El patrón se repitió idéntico en cada intento: procesaba
el prompt, anunciaba que iba a crear el
index.html… y moría con
Streaming response failed. Nunca llegó a escribir
el archivo.
No es un juicio sobre la capacidad del modelo — es un juicio sobre su disponibilidad, que para quien va a trabajar es lo mismo. Un modelo que no responde tiene calidad cero, independientemente de lo que pudiera hacer. Queda fuera de la comparativa por incomparecencia.
Cómo evalué a los seis que sí entregaron
Además de abrirlos en el navegador y mirarlos como los miraría un cliente, hice tres cosas que resultaron ser las que separaron el grano de la paja:
-
Renderizado completo a página entera con
Firefox headless, desactivando
loading="lazy"y forzando los reveals, para que la captura muestre la página real y no una a medio cargar. - Verificación HTTP de cada recurso externo: cada URL de Unsplash, cada CDN, cada hoja de estilos.
- Lectura del JavaScript, no solo del HTML. Ahí es donde estaban escondidas las peores sorpresas.
Modelo por modelo
Mi ganador, y por una razón concreta: es el único que consiguió ser completo sin dejar de ser minimalista. 4365px de alto contra los 4875 de MiMo y los 4964 de Ling, con la misma cantidad de secciones e imágenes. Cuando dos de los seis requisitos empujan en direcciones opuestas — "minimalista" y "navegación, footer, imágenes" — él fue el que mejor negoció.
Es también el único con personalidad de
diseño: curva orgánica en la transición del hero,
overlays en hover sobre la galería, y un
@keyframes pulse-wa que hace latir suavemente
el botón de WhatsApp. Los demás agotan su repertorio en
fadeUp y float.
Y la localización más fina de los seis. No dice "clases de percusión": dice "batería, cajón, percusión latina y ritmos colombianos". No dice "producción musical": dice "FL Studio, Ableton, mezcla y masterización". Eso no es rellenar una plantilla.
Lo que le cobro: ocho enlaces
href="#" y un link "Blog" en el footer que
apunta a una sección inexistente. Navegación que promete y
no cumple.
Empate técnico con Big Pickle en todas las métricas duras. Su ventaja: es el único con hero fotográfico de fondo, con overlay azul degradado. Los demás o pusieron la foto al lado, o no pusieron ninguna. Es la diferencia entre parecer una landing y parecer un ejercicio de maquetación.
Y es, junto a Big Pickle, el único que cuadró todos los grids: 6 cursos en 3×2 exacto, 6 fotos en 3×2 exacto, 3 testimonios en fila. Cero tarjetas huérfanas. Ling y Laguna dejaron colgados en dos secciones cada uno. Elegir números que cierran es criterio de diseño, no suerte.
Detalle que me gustó: usó hola@javastudios.co,
con el TLD colombiano. Nadie se lo pidió.
Nota de reproducibilidad: con la
configuración por defecto opencode no encontraba el
provider. Hubo que forzar variant: medium. Es
un problema de plomería, no del modelo, pero si vas a
repetir el experimento lo vas a encontrar.
El más largo de todos y el que mejor entendió que esto es una landing de negocio, no un ejercicio de CSS. Es el único que armó una tabla de precios — $150.000 / $280.000 / $450.000 COP mensuales, cifras perfectamente plausibles para Soacha — y el que puso testimonios con nombres colombianos. La localización más consciente después de Big Pickle.
Técnicamente hizo la animación como se debe:
IntersectionObserver con
threshold: 0.15 y transitionDelay
escalonado generado en JS. Me costó capturarlo: el
screenshot salía con tres secciones vacías hasta que forcé
el reveal a mano.
Mala suerte con la imagen rota: de sus siete, la única 404 le cayó en la primera tarjeta de cursos — lo primero que el visitante mira después del hero.
Y una desobediencia interesante: el botón flotante de WhatsApp es verde, sobre una paleta que el prompt pedía azul. Comercialmente es la decisión correcta: el verde es reconocimiento de marca instantáneo. Respecto al brief, es incumplimiento. Yo la firmaría, pero hay que nombrarla.
El más rápido por un margen ridículo: 42
segundos, cuando el segundo tardó casi tres veces
más. Y el único que entendió "minimalista" literalmente: 4
secciones, 13 KB, 2621px de alto. La mitad que cualquier
otro. Cero dependencias de JavaScript — el menú hamburguesa
es un onclick inline de una línea.
Tiene el detalle de conversión más fino de los seis: el
SVG oficial de WhatsApp embebido y, sobre todo,
mensaje pre-cargado en el enlace
(wa.me/...?text=Hola%20Javastudios...). Nadie
más lo hizo. Eso es pensar en el usuario que va a dar clic,
no en la checklist.
Su fallo, y es didáctico: la animación
técnicamente existe pero es invisible. Las clases
.fade-up se disparan
al cargar la página, con delays por
:nth-child. Sin
IntersectionObserver, sin trigger de scroll.
Todo lo que está bajo el fold termina de animarse antes de
que llegues a verlo.
Peor: como .fade-up arranca en
opacity: 0, mi primera captura salió con el
<h1>, el párrafo y el CTA
invisibles — la foto quedó tomada a mitad
de animación. Durante casi un segundo el hero está en
blanco. Eso es un golpe directo al LCP.
Su gran virtud, y no la vi hasta el final: es el único de los seis que no inventó una sola cifra de negocio. Ni "500+ estudiantes", ni "desde 2018", ni precios. Volveré sobre esto, porque resultó ser más importante que todo lo demás.
Detalles de descuido: declara
@keyframes fadeIn y nunca lo usa. Su propio
copy del hero promete "canto y más" pero solo hay tres
cursos. Y el hamburguesa es un
<div onclick> sin role, sin
tabindex, sin aria-expanded: en
móvil, un usuario de teclado o lector de pantalla
no puede abrir el menú.
Aquí encontré tres bugs verificables, y uno de ellos es de los que no detectas leyendo el código.
Bug 1 — la tipografía nunca carga.
https://fonts.googleapis.com/css2=Inter:wght@300;400;500;600;700&display=swap
^ falta ?family
Esa URL devuelve 404; la corregida devuelve 200. Lo verifiqué. Inter no carga jamás y la página entera cae al sans-serif del sistema. El modelo diseñó con una tipografía y entregó otra — y ese carácter faltante explica buena parte de por qué se ve pobre.
Bug 2 — usó un icono que no existe.
<i class="fas fa-piano">. Carga Font
Awesome Free 6.5.0 desde cdnjs, pero
fa-piano es un icono Pro. Por eso la
tarjeta "Clases de Piano" muestra un cuadrado azul vacío
mientras guitarra, voz y batería sí renderizan. Eligió 13
iconos correctos y falló justo en el que no verificó.
Bug 3 — el peor. Puso dos imágenes en toda la página. La del hero es 404: lo primero que ve el visitante es una caja gris con el texto alt "Estudiante de música tocando piano". Y la única que sí carga es una foto de dos manos señalando un laptop, en la landing de una escuela de música. No está rota: está mal elegida. Resultado neto: cero imágenes útiles.
Donde me equivoqué y le doy crédito: di
por hecho que su formulario de contacto era un form muerto
sin backend. No lo es. Hace
e.preventDefault(), arma el mensaje y abre
wa.me con el texto codificado. Convierte un
formulario en un canal de WhatsApp sin servidor. Es la
solución más elegante al requisito 4 de toda la tanda.
Ah, y el footer dice © 2024. Dos años
atrasado, cuando DeepSeek acertó 2026 sin ayuda.
Nueve etiquetas <img> sobre seis URLs
únicas. Las verifiqué una por una, primero con
HEAD y luego con GET para
descartar falsos positivos:
404 photo-1494487041770-7a98d0a0c51d
404 photo-1511671782779-cfe11cab67eb
404 photo-1519669556163-dea1aeec3e26
404 photo-1520523839899-80a6bb11b6fd
404 photo-1522201190528-6a4c8f8c5e5b
404 photo-1598622886178-3ba0df9d1b69
control (ID real de otro modelo):
200 photo-1511379938547-c1f69419868d (32 KB)
Seis de seis. Cero aciertos. No falló la red: inventó los seis identificadores. Y como es el único que no puso imagen en el hero, el resultado es que la página no tiene una sola imagen. El requisito 6 no está a medias: está en cero.
console.log('Form submitted:', formData);
alert('¡Gracias por tu mensaje! Te contactaremos pronto.');
this.reset();
El formulario de contacto pide nombre, email, teléfono, curso de interés y mensaje… y lo tira a la consola. Le dice al usuario "te contactaremos pronto" y borra el formulario. Es una mentira ejecutable: cada lead entra, se pierde en silencio, y la persona se queda esperando una llamada que nunca va a llegar.
Compáralo con Laguna, que bajo las mismas restricciones
enrutó su formulario a wa.me. Mismo
problema, una solución honesta y una que no.
Y aquí está lo incómodo: North es el tercero más lento y produjo 803 líneas de HTML que, leídas, parecen perfectamente correctas. Nada en el código delata las seis imágenes muertas ni el formulario que engaña. Solo aparecen al abrir el navegador y al hacer peticiones HTTP reales.
Los tres patrones que atraviesan todo
Lo individual es anecdótico. Lo que se repite en los seis es lo que de verdad importa.
1. Cinco de seis inventaron estadísticas de negocio
Nunca di un teléfono, ni precios, ni años de trayectoria, ni número de estudiantes. Esto es lo que apareció igual — lo conté a mano sobre los seis archivos:
- "500+ estudiantes" — Ling, Laguna, MiMo y Big Pickle
- "Desde 2018" — Ling, North, MiMo y Big Pickle. Laguna prefirió "desde 2014"
- "15+ profesores", "8 años", "10+ años de experiencia"
- Precios concretos en COP — Ling ($150.000 / $280.000 / $450.000) y North ($150.000 / $170.000 / $180.000)
- Horarios de atención, testimonios firmados con nombre y apellido, "Recital trimestral"
La excepción, y merece crédito: DeepSeek. Es el único de los seis que no fabricó una sola cifra. Ni estudiantes, ni años, ni precios, ni profesores. Se limitó a copy que no afirma nada verificable. Lo único que se inventó fue una oferta — "clase de prueba gratuita" — que sigue siendo un compromiso que nadie autorizó, pero está a años luz de atribuirle a un negocio 500 estudiantes que no tiene.
Un punto a favor de todos, eso sí: los seis usaron el mismo
teléfono, +57 300 123 4567. Es un placeholder
transparente — nadie va a confundirlo con un número real. Ahí
sí señalaron el hueco en vez de taparlo, que es exactamente lo
que debieron hacer con el resto.
Ninguna checklist de "cumplió/no cumplió los 6 requisitos" detecta esto. Y si un cliente publica esa página tal cual, está haciendo publicidad engañosa — que en Colombia es competencia de la SIC. Los testimonios son todavía peor: son citas atribuidas a personas con nombre y apellido que no existen.
Lo peligroso no es que el modelo se equivoque en el CSS. Es que rellene los huecos con afirmaciones falsas redactadas con total naturalidad, y que revisar eso requiera leer cada frase pensando "¿esto me lo dijeron o se lo inventó?".
2. La mitad falló la animación por el mismo motivo
Tres de seis (DeepSeek, Laguna, North) implementaron
@keyframes que se disparan al cargar la página, sin
IntersectionObserver. El resultado es idéntico en
los tres: todo lo que está bajo el fold termina su animación
antes de que el usuario llegue a esa altura.
Cumplen la letra del requisito 3 y no la intención.
Si revisas el código, hay animación. Si abres la página, no la
ves. Los otros tres (Big Pickle, MiMo, Ling) sí usaron
IntersectionObserver, y la diferencia al navegar
es enorme.
3. Todos rompieron el requisito de "colores azules" en el mismo punto
Cada modelo que puso un botón destacado de WhatsApp lo puso verde. Es incumplimiento del requisito 1 y es, casi seguro, la decisión correcta: el verde de WhatsApp es reconocimiento de marca instantáneo. Es el único caso del experimento donde desobedecer el brief mejora el resultado.
El hallazgo que no esperaba: cómo alucinan las imágenes
Cuando vi que North tenía las seis imágenes rotas, se me ocurrió cruzar todos los IDs de Unsplash de los seis modelos. Hay 30 IDs únicos en total, y el patrón que salió es limpísimo:
| Tipo de ID | Cantidad | Rotos | Tasa de fallo |
|---|---|---|---|
| Elegido por 2 o 3 modelos de forma independiente | 7 | 0 | 0% |
| Usado por un solo modelo | 23 | 11 | 48% |
Los siete IDs compartidos funcionan todos. Ninguna excepción. Y casi la mitad de los que aparecen una sola vez están muertos.
El caso más elocuente son MiMo y Big Pickle, que eligieron la misma foto:
MiMo photo-1598488035139-bdbb2231cb64 404
Big Pickle photo-1598488035139-bdbb2231ce04 200
mismo prefijo ^ ^ sufijo alucinado
Ahí se ve el mecanismo: los modelos memorizan la parte estable del ID — el timestamp — y alucinan el hash final. Los IDs que varios modelos comparten son los que están genuinamente en los datos de entrenamiento: las fotos virales de Unsplash, vistas miles de veces. Los que aparecen una sola vez son, la mitad de las veces, invención pura con la forma correcta.
Si un modelo te da una URL de Unsplash, verifícala siempre. Y si dos modelos distintos te dan la misma, casi con seguridad es real. Es una forma barata de auto-validación: pídele las imágenes a dos modelos y quédate con la intersección.
Tabla final
| # | Modelo | Tiempo | Peso | Alto | Imgs OK | Reveal | Año | Veredicto |
|---|---|---|---|---|---|---|---|---|
| 1 | Big Pickle | 2m 05s | 26 KB | 4365px | 10/11 | sí | 2026 | Completo y compacto |
| 2 | MiMo v2.5 | 1m 53s | 24 KB | 4875px | 10/11 | sí | 2026 | Empate técnico |
| 3 | Ling 3.0 Flash | 2m 17s | 34 KB | 4964px | 6/7 | sí | 2026 | El más comercial |
| 4 | DeepSeek V4 Flash | 42s | 13 KB | 2621px | 3/4 | no | 2026 | El minimalista real |
| 5 | Laguna S 2.1 | 20m 48s* | 29 KB | 3913px | 1/2 | no | 2024 | Fuente 404, icono Pro, foto de laptop |
| 6 | North Mini Code | 4m 17s | 26 KB | 4814px | 0/6 | no | 2024 | Cero imágenes, formulario que miente |
| — | Nemotron 3 Ultra | Streaming response failed — no entregó | ||||||
Qué me llevo
Sí, los modelos gratis de opencode sirven. Tres de siete entregaron algo que un freelance podría ajustar y cobrar el mismo día. Para prototipar, para arrancar un proyecto, para tener algo que enseñarle a un cliente en dos minutos: perfectamente utilizables.
Pero el experimento me dejó tres cosas más útiles que el ranking:
Uno: velocidad y calidad no correlacionan. El más rápido (DeepSeek, 42s) quedó cuarto. El segundo más lento (North, 4m17s) quedó último. Y el que más tiempo me costó (Laguna, 20 minutos) fue el penúltimo. Esperar más no compra nada.
Dos: revisar el código no basta. Este es el aprendizaje que me llevo de verdad. Las seis imágenes muertas de North, la fuente 404 de Laguna, su icono Pro inexistente y el formulario que le miente al usuario: ninguno de esos fallos se ve leyendo el HTML. Todos tienen sintaxis impecable. Aparecen al renderizar y al hacer peticiones HTTP. Si tu proceso de validación termina en "leí el diff y se ve bien", vas a publicar páginas rotas.
Tres: la alucinación de datos es el problema serio. Cinco de seis inventaron cifras de negocio con total naturalidad. Un enlace roto lo ves; un "500+ estudiantes satisfechos" falso pasa a producción sin que nadie parpadee. Y a diferencia del CSS, ese error tiene consecuencias legales para tu cliente. Que DeepSeek —el modelo más rápido y más simple— fuera el único que se abstuvo sugiere que no es una limitación técnica, sino una decisión de entrenamiento.
Última nota, y es la que más me hace pensar: todo esto se arregla con andamiaje. Un skill que obligue a verificar URLs. Un MCP que consulte la API real de Unsplash. Una instrucción que prohíba inventar datos no proporcionados. Un paso de spec-driven que fije el inventario de secciones antes de escribir una línea.
Nada de eso estaba aquí, y ese era el punto. Esta prueba mide el piso. La conclusión es que el piso de los modelos gratuitos está sorprendentemente alto en maquetación y sorprendentemente bajo en veracidad — y que la diferencia entre un resultado usable y uno peligroso no la pone el modelo. La pones tú, con lo que le montas encima.