bsanchez@codesan.dev:~/blog$ _
ES
~$ cat opencode-free-models.md

7 free opencode models, one prompt: what each one actually shipped

opencode ships a batch of free models and the obvious question is which ones are worth using. I couldn't find a comparison that convinced me, so I ran my own: one prompt, seven models, zero help. What follows is the log of that morning.

Spoiler on the result I didn't see coming: the worst failure wasn't design or code. It was something no code review would have caught, and I needed HTTP requests to find it.

The rules: everything vanilla

This matters, because it defines what the experiment measures and what it doesn't. The test was deliberately raw:

  • No skills. No instructions loaded.
  • No MCPs. No context servers connected.
  • No spec-driven development. No upfront spec document, no plan, no phases.
  • No agentic techniques. No forced chain-of-thought, no self-critique, no iteration, no "review your work".
  • A single turn. I pasted the prompt, waited, and whatever came out is what I graded. No corrections, no second chances.

This does not measure each model's ceiling. Decent agentic scaffolding would have fixed half the problems I found. What it measures is the floor: what the model hands you when you ask the way you'd ask a colleague, no ceremony. And when you're deciding which free model is worth your time, the floor is exactly what you want to know.

The prompt, verbatim

PROMPT SENT TO ALL 7 MODELS

(original in Spanish) Build a landing page to promote a music school in Soacha, Cundinamarca called Javastudios. It must meet the following requirements:

  1. Use blue colors
  2. Have a very attractive minimalist design
  3. Have at least a subtle animation
  4. Have a call to action that leads to whatsapp
  5. Have navigation and footer
  6. Have images from Unsplash

Six verifiable requirements, a real local business, specific enough that the model can't coast on autopilot. No further context: no phone number, no pricing, no years in business, no course catalog. Hold on to that detail — it ends up being the heart of this article.

The contenders

Model Time Run notes
DeepSeek V4 Flash 42s No friction
MiMo v2.5 1m 53s With default it couldn't find the provider; needed variant: medium
Big Pickle 2m 05s Wrote into its own subfolder
Ling 3.0 Flash 2m 17s No friction
North Mini Code 4m 17s No friction
Laguna S 2.1 20m 48s* *Almost entirely rate-limit waits
Nemotron 3 Ultra Streaming response failed on every attempt

Let's start with the one that never made it to the track.

Nemotron 3 Ultra: announced it, never delivered

The only "Ultra" in the batch and the only one that produced not a single line. The pattern repeated identically every attempt: it processed the prompt, announced it was going to create index.html… and died with Streaming response failed. It never wrote the file.

That's not a judgment on the model's capability — it's a judgment on its availability, which for anyone trying to get work done is the same thing. A model that doesn't respond has zero quality, regardless of what it might have been able to do. It's out of the comparison by no-show.

How I graded the six that did deliver

Beyond opening them in a browser and looking at them the way a client would, I did three things that turned out to separate the wheat from the chaff:

  1. Full-page headless rendering with Firefox, disabling loading="lazy" and forcing reveals, so the screenshot shows the real page and not a half-loaded one.
  2. HTTP verification of every external resource: every Unsplash URL, every CDN, every stylesheet.
  3. Reading the JavaScript, not just the HTML. That's where the worst surprises were hiding.

Model by model

[1] Big Pickle 2m 05s · 26 KB · 575 lines
Height: 4365px Images: 10/11 Scroll reveal: yes Footer year: 2026
Landing page by Big Pickle: blue hero with trumpet, 6-course grid, gallery and testimonials
Big Pickle — organic curve on the hero, 3×2 grid with no orphans. The gap in the gallery is its single 404.

My winner, for one concrete reason: it's the only one that managed to be complete without giving up on minimalism. 4365px tall against MiMo's 4875 and Ling's 4964, with the same number of sections and images. When two of the six requirements pull in opposite directions — "minimalist" versus "navigation, footer, images" — it negotiated best.

It's also the only one with actual design personality: an organic curve on the hero transition, hover overlays on the gallery, and a @keyframes pulse-wa that gently pulses the WhatsApp button. The others exhaust their repertoire on fadeUp and float.

And the sharpest localization of the six. It doesn't say "percussion classes": it says "drums, cajón, Latin percussion and Colombian rhythms". It doesn't say "music production": it says "FL Studio, Ableton, mixing and mastering". That's not filling in a template.

What I hold against it: eight href="#" links and a "Blog" link in the footer pointing at a section that doesn't exist. Navigation that promises and doesn't deliver.

[2] MiMo v2.5 1m 53s · 24 KB · 538 lines
Height: 4875px Images: 10/11 Scroll reveal: yes Footer year: 2026
Landing page by MiMo: hero with background photo and blue overlay, 6 courses, 3x2 gallery
MiMo — the only one with a full-bleed photo hero. The grey box next to the stats is its broken image.

A technical tie with Big Pickle on every hard metric. Its edge: it's the only one with a full-bleed photographic hero, with a blue gradient overlay. The others either put the photo beside the text or skipped it entirely. That's the difference between looking like a landing page and looking like a markup exercise.

And it's the only one besides Big Pickle that squared every grid: 6 courses in an exact 3×2, 6 photos in an exact 3×2, 3 testimonials in a row. Zero orphaned cards. Ling and Laguna left danglers in two sections each. Picking numbers that close is design judgment, not luck.

A detail I liked: it used hola@javastudios.co, with the Colombian TLD. Nobody asked it to.

Reproducibility note: with the default config opencode couldn't find the provider. It needed variant: medium. That's plumbing, not the model, but if you rerun this experiment you'll hit it.

[3] Ling 3.0 Flash 2m 17s · 34 KB · 1240 lines
Height: 4964px Images: 6/7 Scroll reveal: yes Footer year: 2026
Landing page by Ling: blue hero, courses section, COP pricing table and testimonials
Ling — the only one that built a pricing table. The first course card is the one that lost its image.

The longest of the batch, and the one that best understood this is a business landing page, not a CSS exercise. It's the only one that built a pricing table — $150,000 / $280,000 / $450,000 COP per month, entirely plausible figures for Soacha — and the one that wrote testimonials with Colombian names. The most deliberate localization after Big Pickle.

Technically it did the animation right: IntersectionObserver with threshold: 0.15 and a staggered transitionDelay generated in JS. It gave me trouble to capture: my screenshot came out with three empty sections until I forced the reveal by hand.

Bad luck with the broken image: of its seven, the single 404 landed on the first course card — the first thing a visitor looks at after the hero.

And an interesting act of disobedience: the floating WhatsApp button is green, on a palette the prompt asked to be blue. Commercially it's the right call: green is instant brand recognition. Against the brief, it's non-compliance. I'd sign off on it, but it deserves to be named.

[4] DeepSeek V4 Flash 42s · 13 KB · 363 lines
Height: 2621px Images: 3/4 Scroll reveal: no Footer year: 2026
Landing page by DeepSeek: hero with side photo, three course cards, gallery and blue CTA
DeepSeek — half the height of everyone else. The cleanest and the most incomplete at the same time.

Fastest by a ridiculous margin: 42 seconds, when second place took almost three times longer. And the only one that read "minimalist" literally: 4 sections, 13 KB, 2621px tall. Half of anyone else. Zero JavaScript dependencies — the hamburger menu is a one-line inline onclick.

It has the sharpest conversion detail of the six: the official WhatsApp SVG inlined and, above all, a pre-filled message in the link (wa.me/...?text=Hola%20Javastudios...). Nobody else did it. That's thinking about the person who will click, not about the checklist.

Its failure, and it's instructive: the animation technically exists but is invisible. The .fade-up classes fire on page load, with :nth-child delays. No IntersectionObserver, no scroll trigger. Everything below the fold finishes animating before you ever scroll to it.

Worse: since .fade-up starts at opacity: 0, my first screenshot came out with the <h1>, the paragraph and the CTA invisible — the shot landed mid-animation. For nearly a second the hero is blank. That's a direct hit to LCP.

Its great virtue, which I didn't spot until the end: it's the only one of the six that invented no business figures at all. No "500+ students", no "since 2018", no pricing. I'll come back to this, because it turned out to matter more than everything else.

Sloppiness: it declares @keyframes fadeIn and never uses it. Its own hero copy promises "voice and more" but there are only three courses. And the hamburger is a <div onclick> with no role, no tabindex, no aria-expanded: on mobile, a keyboard or screen-reader user cannot open the menu.

[5] Laguna S 2.1 20m 48s* · 29 KB · 937 lines
Height: 3913px Images: 1/2 Scroll reveal: no Footer year: 2024
Landing page by Laguna: hero with no image, service cards, and a laptop photo in the About section
Laguna — hero image broken, and the only photo that loads on the whole page is a laptop.

Three verifiable bugs here, and one of them is the kind you don't catch by reading code.

Bug 1 — the typeface never loads.

https://fonts.googleapis.com/css2=Inter:wght@300;400;500;600;700&display=swap
                                  ^ missing ?family

That URL returns 404; the corrected one returns 200. I checked. Inter never loads and the whole page falls back to the system sans-serif. The model designed with one typeface and shipped another — and that single missing character explains a good chunk of why it looks cheap.

Bug 2 — it used an icon that doesn't exist. <i class="fas fa-piano">. It loads Font Awesome Free 6.5.0 from cdnjs, but fa-piano is a Pro icon. That's why the "Piano Classes" card shows an empty blue square while guitar, voice and drums render fine. It picked 13 correct icons and failed on the one it didn't verify.

Bug 3 — the worst one. It placed two images on the entire page. The hero one is a 404: the first thing a visitor sees is a grey box with the alt text "Music student playing piano". And the only one that does load is a photo of two hands pointing at a laptop, on a music school landing page. It's not broken: it's wrong. Net result: zero usable images.

Where I was wrong, and credit where it's due: I assumed its contact form was a dead form with no backend. It isn't. It calls e.preventDefault(), builds the message and opens wa.me with the encoded text. It turns a form into a WhatsApp channel with no server. It's the most elegant solution to requirement 4 in the whole batch.

Oh, and the footer says © 2024. Two years behind, when DeepSeek got 2026 right unprompted.

[6] North Mini Code 4m 17s · 26 KB · 803 lines
Height: 4814px Images: 0/6 Scroll reveal: no Footer year: 2024
Landing page by North: Photo Gallery section showing six empty rectangles with only alt text
North — the section is still called "Photo Gallery". Those are six empty rectangles.

Nine <img> tags over six unique URLs. I checked each one, first with HEAD and then with GET to rule out false positives:

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 (real ID from another model):
200  photo-1511379938547-c1f69419868d  (32 KB)

Six out of six. Zero hits. The network didn't fail: it invented all six identifiers. And since it's the only model that put no image in the hero, the result is that the page has not a single image on it. Requirement 6 isn't half-met: it's at zero.

THE MOST SERIOUS FAILURE, AND IT'S NOT VISUAL
console.log('Form submitted:', formData);
alert('¡Gracias por tu mensaje! Te contactaremos pronto.');
this.reset();

The contact form asks for name, email, phone, course of interest and message… and dumps it to the console. It tells the user "we'll contact you soon" and clears the form. It's an executable lie: every lead comes in, vanishes silently, and the person waits for a call that will never come.

Compare that with Laguna, which under the same constraints routed its form to wa.me. Same problem, one honest solution and one that isn't.

And here's the uncomfortable part: North is the third slowest and produced 803 lines of HTML that, read on the page, look perfectly correct. Nothing in the code betrays the six dead images or the lying form. They only surface when you open a browser and make real HTTP requests.


The three patterns that run through everything

Individual results are anecdotes. What repeats across all six is what actually matters.

1. Five of six invented business statistics

I never gave a phone number, pricing, years in business or student count. Here's what showed up anyway — counted by hand across all six files:

  • "500+ students" — Ling, Laguna, MiMo and Big Pickle
  • "Since 2018" — Ling, North, MiMo and Big Pickle. Laguna went with "since 2014"
  • "15+ teachers", "8 years", "10+ years of experience"
  • Concrete COP pricing — Ling ($150,000 / $280,000 / $450,000) and North ($150,000 / $170,000 / $180,000)
  • Opening hours, testimonials signed with full names, "quarterly recital"

The exception, and it deserves credit: DeepSeek. It's the only one of the six that fabricated not a single figure. No students, no years, no pricing, no teachers. It stuck to copy that asserts nothing verifiable. The only thing it made up was an offer — "free trial class" — which is still a commitment nobody authorized, but it's light years away from crediting a business with 500 students it doesn't have.

One point in everyone's favor, though: all six used the same phone number, +57 300 123 4567. That's a transparent placeholder — nobody's mistaking it for a real number. There they flagged the gap instead of papering over it, which is exactly what they should have done with the rest.

THIS IS THE REAL RISK

No "met/didn't meet the 6 requirements" checklist catches this. And if a client publishes that page as-is, they're running false advertising — which in Colombia falls under the SIC. The testimonials are worse still: they're quotes attributed to named people who don't exist.

The dangerous part isn't the model getting CSS wrong. It's that it fills the gaps with false claims written with total confidence, and that reviewing for it means reading every sentence asking "was I told this, or did it make it up?"

2. Half of them failed the animation for the same reason

Three of six (DeepSeek, Laguna, North) implemented @keyframes that fire on page load, with no IntersectionObserver. The result is identical in all three: everything below the fold finishes animating before the user scrolls that far.

They satisfy the letter of requirement 3 and not its intent. Review the code and there's animation. Open the page and you never see it. The other three (Big Pickle, MiMo, Ling) did use IntersectionObserver, and the difference while scrolling is enormous.

3. Every one broke the "blue colors" requirement at the same spot

Every model that added a prominent WhatsApp button made it green. It breaks requirement 1 and it's almost certainly the right call: WhatsApp green is instant brand recognition. It's the one case in this experiment where disobeying the brief improves the outcome.


The finding I didn't expect: how images get hallucinated

Once I saw North had all six images broken, I cross-referenced every Unsplash ID across all six models. There are 30 unique IDs total, and the pattern is remarkably clean:

Kind of ID Count Broken Failure rate
Picked independently by 2 or 3 models 7 0 0%
Used by a single model 23 11 48%

All seven shared IDs work. No exceptions. And nearly half of the ones that appear only once are dead.

The most telling case is MiMo and Big Pickle, which picked the same photo:

MiMo        photo-1598488035139-bdbb2231cb64   404
Big Pickle  photo-1598488035139-bdbb2231ce04   200
                        same prefix ^   ^ hallucinated suffix

That exposes the mechanism: models memorize the stable part of the ID — the timestamp — and hallucinate the trailing hash. The IDs several models share are the ones genuinely in the training data: the viral Unsplash photos, seen thousands of times. The ones that appear only once are, half the time, pure invention with the right shape.

PRACTICAL HEURISTIC

If a model hands you an Unsplash URL, always verify it. And if two different models hand you the same one, it's almost certainly real. It's a cheap form of self-validation: ask two models for images and keep the intersection.


Final table

# Model Time Size Height Imgs OK Reveal Year Verdict
1 Big Pickle 2m 05s 26 KB 4365px 10/11 yes 2026 Complete and compact
2 MiMo v2.5 1m 53s 24 KB 4875px 10/11 yes 2026 Technical tie
3 Ling 3.0 Flash 2m 17s 34 KB 4964px 6/7 yes 2026 Most commercial
4 DeepSeek V4 Flash 42s 13 KB 2621px 3/4 no 2026 The real minimalist
5 Laguna S 2.1 20m 48s* 29 KB 3913px 1/2 no 2024 404 font, Pro icon, laptop photo
6 North Mini Code 4m 17s 26 KB 4814px 0/6 no 2024 Zero images, a form that lies
Nemotron 3 Ultra Streaming response failed — did not deliver

What I take away

Yes, opencode's free models are usable. Three of seven shipped something a freelancer could adjust and invoice the same day. For prototyping, for kicking off a project, for having something to show a client in two minutes: perfectly serviceable.

But the experiment left me three things more useful than the ranking:

One: speed and quality don't correlate. The fastest (DeepSeek, 42s) came fourth. The second slowest (North, 4m17s) came last. And the one that cost me the most time (Laguna, 20 minutes) came second to last. Waiting longer buys you nothing.

Two: reviewing the code isn't enough. This is the lesson I actually walk away with. North's six dead images, Laguna's 404 font, its nonexistent Pro icon and the form that lies to the user: none of those failures are visible in the HTML. All of them have impeccable syntax. They appear on render and on HTTP requests. If your validation process ends at "I read the diff and it looks fine", you're going to ship broken pages.

Three: data hallucination is the serious problem. Five of six invented business figures with total confidence. A broken link you can see; a fake "500+ satisfied students" ships to production without anyone blinking. And unlike CSS, that mistake has legal consequences for your client. That DeepSeek — the fastest and simplest model — was the only one to abstain suggests this isn't a technical limitation but a training decision.

One last note, and it's the one that gives me the most pause: all of this is fixable with scaffolding. A skill that forces URL verification. An MCP that queries the real Unsplash API. An instruction that forbids inventing data that wasn't provided. A spec-driven step that locks the section inventory before a line gets written.

None of that was here, and that was the point. This test measures the floor. The conclusion is that the floor of free models is surprisingly high on markup and surprisingly low on truthfulness — and that the difference between a usable result and a dangerous one isn't set by the model. You set it, with what you build around it.

~$ cd ..