How I use vibe coding to hit 100 on Lighthouse for performance, accessibility, and SEO

Introduction
I want to explain how wrong people can be when using vibe coding to create incredibly beautiful sites. Everyone focuses on the surface beauty, that look that impresses at first glance, when in reality what actually matters is how good and performant your product is alongside that same beauty. Beauty without performance is just a facade.
In this tutorial, you'll learn the exact workflow I use to hit 100% on Lighthouse in performance, accessibility, SEO, and best practices, using vibe coding with Cloud Code and DeepSeek. Basically, it's the process I apply to all my web projects, and it's what separates a real portfolio from a facade portfolio.
Estimated reading time: 9 min
The real portfolio is when someone opens your site, hits F12, and runs Lighthouse. That's what matters.
Prerequisites
Before we get going, let me be straight with you about what you'll need to follow this flow without tripping up. Software first: Cloud Code, which is my go-to harness for vibe coding, and an injection of DeepSeek V4 Pro, the model that changed the game after the August 12 update. You'll also need a Chromium browser with Lighthouse available, and if you want to run metrics automatically, a headless browser does the trick.
On knowledge, ideally you've got some familiarity with vibe coding, even basic, plus a grasp of web performance, accessibility, and SEO. You don't need to be an expert, but understanding what each of those areas means goes a long way when you're evaluating the AI's suggestions.
On environment, any Node.js or JavaScript web project works, when in reality what matters is that your stack runs on a Chromium browser, because that's where Lighthouse runs and reports everything we need.
Why this matters
The problem with apparent beauty is that it fools everyone, including the site owner. You put up a landing page with pretty effects, smooth animations, that flawless aesthetic, and you think the job is done. But the truth is, what sustains a product is how performant it is, how accessible, how well it ranks in SEO, and how well it follows development best practices. And Lighthouse reports exactly those four things in any Chromium browser, which is basically the metric that separates a facade site from a real site.
If the developer doesn't do accessibility on their own site, how are they going to do it for a client? If they don't do performance on their own site, how are they going to do it for a client? If the best practices aren't on their site, how are they going to be on the client's? I've been applying this approach to all my web projects, and in Node.js and JavaScript projects I use other metric tools, but the focus here is what Lighthouse can tell you about any page.
So basically, the real portfolio is when you open your site, hit F12, and run Lighthouse on it. That's your real portfolio, and that's why it has to be perfect.
Setup
Before anything else, you need to set up a vibe coding environment that actually delivers results, not just pretty surfaces. I use Cloud Code because it has, in my opinion, the best harness for managing the development flow with AI agents, but the magic happens when you inject DeepSeek into it. I'll show you the config file I use, basically a config.json inside the project's .cloudcode folder.
// .cloudcode/config.json
{
"provider": {
"type": "openai",
"apiKey": "${DEEPSEEK_API_KEY}",
"baseUrl": "https://api.deepseek.com/v1"
},
"model": {
"name": "deepseek-chat",
"version": "deepseek-v4-pro",
"parameters": {
"temperature": 0.3,
"maxTokens": 4096
}
},
"harness": {
"waves": true,
"subAgents": true,
"lighthouseIntegration": true
}
}
You might be wondering why I use DeepSeek instead of other models, and the answer is that after the August 12 update, DeepSeek V4 Pro reached a reasoning level equivalent to GLM 5.2, which was the state of the art for open source models, at a price that basically no competitor can match, when in fact what matters is having a model cheap and smart enough to make optimization decisions without blowing the project budget. The Cloud Code harness manages the whole flow of development waves, sub-agents, and Lighthouse integration, and DeepSeek comes in as the reasoning engine that proposes and iterates on changes. It's a combination that, in practice, lets me focus on real quality while the AI handles the boring experimentation.
Step 1: Configuring DeepSeek in Cloud Code
I personally really like using Cloud Code, which has the best harness for this kind of flow, but the magic happens when you inject DeepSeek as the reasoning model. After the August updates, especially the one on the 12th, DeepSeek V4 Pro reached the same reasoning level as a GLM 5.2, which was our SOTA for open source models, at a price that only DeepSeek can put on the market. That changes the game because you can iterate fast without worrying about blowing the budget.
The setup is straightforward. You define the model in Cloud Code's config file and point it to DeepSeek's endpoint:
# Sets DeepSeek V4 Pro as the reasoning model in Cloud Code
cloud-code config set model deepseek-v4-pro
cloud-code config set model.thinking enabled true
cloud-code config set model.endpoint https://api.deepseek.com/v1
What matters here is model.thinking enabled true. That's what activates the reasoning mode, which is what lets the AI think before proposing optimizations. Without it, you're just using an expensive autocomplete.
One tip: before moving to the next step, run cloud-code config get model and check if the active model is DeepSeek V4 Pro. I once lost an entire afternoon optimizing with the wrong model, thinking the problem was the code when it was actually the configuration.
Step 2: Integrating Lighthouse into the flow
With DeepSeek running on Cloud Code, the next step is making Lighthouse part of your development cycle, not an audit you run once at the end, after everything's already done. The way I do it is integrating Lighthouse directly into the flow with a headless browser, and your build can call this integration at various stages you define, with multiple subagents, and using development waves.
The concept of waves is basically this: in each wave, you run a metric, let the AI free to propose experiments, and at the end it reports its ideas to you. You fix what didn't make sense and try again if an experiment degrades the product in a way that isn't worth the performance gain.
The script below is an example of how to run Lighthouse via headless browser in Node.js. It opens the URL, runs the audit, and saves the report as JSON. You can plug this into a cron, into a hook in your vibe coding harness, or call it manually whenever you want to measure a wave:
// lighthouse-runner.js
import { chromium } from 'playwright';
import lighthouse from 'lighthouse';
const url = process.env.URL || 'http://localhost:3000';
const browser = await chromium.launch({ headless: true });
const { port } = await browser.startServer();
const { lhr } = await lighthouse(url, {
port,
output: 'json',
logLevel: 'info',
onlyCategories: ['performance', 'accessibility', 'seo', 'best-practices'],
}, {
extends: 'lighthouse:default',
settings: {
formFactor: 'desktop',
throttling: { rttMs: 40, throughputKbps: 10240, cpuSlowdownMultiplier: 1 },
},
});
console.log(`Performance: ${lhr.categories.performance.score * 100}`);
console.log(`Accessibility: ${lhr.categories.accessibility.score * 100}`);
console.log(`SEO: ${lhr.categories.seo.score * 100}`);
await browser.close();
What this allows is continuous measurement without interrupting the vibe coding flow. At each wave, you have a concrete number to decide if the change the AI proposed is worth it, instead of relying on guesswork or the "apparent beauty" of the visual result.
Step 3: Running metrics and experiments
With Lighthouse wired into the flow, the next step is letting the AI actually do the work. In each wave, you give it the freedom to propose optimizations, run Lighthouse again, and see what changes. The idea is simple: instead of you sitting there guessing what improves performance, the AI tests hypotheses on its own and brings you the results.
Here's a script that fires off an experimentation wave. It runs Lighthouse, collects the metrics, asks the AI to suggest an optimization, and runs everything again to compare:
// scripts/experiment-wave.js
const { runLighthouse } = require('./lighthouse');
const { askAI } = require('./ai');
async function runWave(url, context) {
const before = await runLighthouse(url);
console.log('Metrics before:', before);
const suggestion = await askAI(`
Lighthouse reported: ${JSON.stringify(before)}.
Propose an optimization and implement it.
`);
await suggestion.apply();
const after = await runLighthouse(url);
console.log('Metrics after:', after);
return {
before,
after,
suggestion: suggestion.summary(),
};
}
At the end of each wave, the AI reports its ideas to you, with the before and after. You can correct those ideas or discard them if the gain isn't worth it. What speeds up the hunt for 100% is exactly that autonomy: the AI tries things you might not even think of, and you just validate what makes sense. That turns the optimization process into something continuous, not a manual effort you do once and forget.
That's how I got the result in the video below, with Lighthouse at 100% across the board. Each wave was a small win, and in the end the confetti showed up.
Now, if a wave degrades the product in a way that isn't worth it, that's where the next step comes in: fix and iterate until the quality holds.
Step 4: Fixing regressions and iterating
Actually, the thing that most separates people who use vibe coding for a facade portfolio is this: knowing what to do when experimentation degrades the product. It happens all the time, the AI proposes an optimization that seems obvious, but in practice it breaks the page's visual hierarchy, or the performance gain isn't worth what you lose in accessibility. And the beauty of the cycle is exactly there, in the fix.
I structured this with a rollback function that runs at the end of each wave, comparing the Lighthouse result on the main branch with the experimentation branch:
// rollback.js
const categories = ['performance', 'accessibility', 'seo', 'bestPractices'];
const tolerance = 2.5;
function decideToKeep(before, after) {
const degraded = categories.filter((cat) => after[cat] < before[cat] - tolerance);
if (degraded.length > 0) {
console.warn('Reverting wave, loss in:', degraded.join(', '));
rollback();
return false;
}
acceptWave();
return true;
}
The logic is straightforward: a tolerance of 2.5 points per category, if any value drops beyond that, the experiment is discarded and the baseline comes back. Sure, losing 2 points in accessibility to gain 5 in performance can be an interesting trade-off, but I can adjust the tolerance on each round, or reject the wave anyway. The final call is mine, the script doesn't call the shots.
It's this repeated cycle that keeps the quality up: the AI generates, I run Lighthouse again, when it gets worse I undo it, when it gets better I incorporate it and take another one. I use this spectrum on all my web projects, from personal tests to client sites, and it's basically what left me at ease with response across the board. When someone opens the portfolio and hits F12, the 100% across everything isn't a magic formula, it's the result of chasing down the fixes until only what works is left.
Common Issues
Look, the whole flow works nicely in theory, but in practice there are always rough edges. The most common problem I see is Lighthouse simply not running in headless mode. You fire off the command, and nothing happens. Most of the time it's because the Chromium flags are missing, without the --headless=new flag or --no-sandbox in restricted environments, the headless just won't kick off. So check the flags before you start debugging the AI code.
Another recurring issue is DeepSeek not responding the way you'd expect. Then you check the injection in Cloud Code and realize the model version is wrong. Since the update on August 12, DeepSeek V4 Pro is the one that actually has decent reasoning. If you're using an older version, the AI is gonna suggest nonsense. Just run deepseek --version in the terminal to be sure.
And then there are experiments that make performance worse, the AI proposes an optimization, you apply it, and Lighthouse drops from 98 to 70. This happens when it touches things it shouldn't, like fonts loaded synchronously or images without lazy loading. The trick is to run Lighthouse manually after each wave, before accepting the suggestion. Sounds obvious, but we always want to blindly trust the AI. Basically, you need to validate with your own eyes; the machine doesn't understand the context of your project.
Wrapping Up
Now the workflow is in your hands. Grab any web project you already have, run Lighthouse on it today, and see what your current score is. Then apply the same wave cycle with the AI proposing experiments and measuring the result on each iteration, and basically you'll watch the number climb without having to memorize accessibility docs. And honestly, that's what separates people who just stack frameworks from people who actually ship a real product.
That's your real portfolio. It's not the pretty landing page with the fancy scroll animation, it's what the browser reports when someone hits F12 and runs the audit. That's why your portfolio has to be perfect, because it's the only metric a client or a recruiter can see without asking you to explain it.
If you hit 100, tell me. Send the screenshot in the team Slack or on WhatsApp, because when you see those Lighthouse fireworks for the first time, it's hard not to want to share it. And if you get stuck at 90, go back to step 4 and let the AI run one more wave. The workflow holds up.