Skip to main content

SEO for vibe coded sites: what to check in Lovable, v0 and Bolt output

Sites generated by Lovable, v0, Bolt and Replit tend to miss the same checks. This is the list, the audit rule that catches each one, and how to hand the whole batch back to the agent that built the site.

A site built in an afternoon with Lovable, v0, Bolt or Replit usually works. The pages load, the layout holds up, the forms submit. Then it fails to appear in search, and the cause is hard to locate because nothing on screen looks broken.

The same defects turn up across all four platforms, because they optimise for the same thing: a preview that looks correct in a browser. Everything a crawler needs that a browser does not falls outside that goal. The list below is what to check, not a guarantee your build has all of it.

The defect list

The content is not in the HTML

Generated apps commonly render client-side. The server returns an empty root element and JavaScript fills it in. Google renders JavaScript eventually, but most AI agents and many crawlers read the raw response and find nothing there.

One command tells you which case you are in:

curl -s https://your-site.example | grep -c "some sentence from your homepage"

A zero means the content does not exist until JavaScript runs. ax/content-without-js measures the same thing across the site, comparing the raw HTML against a separately rendered DOM and flagging main content that only appears after JavaScript runs. Fix this before anything further down the list, because the rest of the list applies to a page a crawler can already read.

Every route shares one title

The generator writes a title into the app shell and often gives the router no way to change it. Every page then returns the same one, so search results cannot distinguish a pricing page from a homepage.

Three rules cover this. core/meta-title checks presence and length, core/title-unique checks uniqueness across the site, and content/duplicate-title reports which pages collide. Meta descriptions repeat the pattern, and core/meta-description and content/duplicate-description cover them.

No sitemap, no robots.txt

Neither file is needed for a preview to work, so neither is usually generated. crawl/sitemap-exists checks for an XML sitemap and whether robots.txt references it. crawl/robots-txt checks robots.txt exists, parses as valid syntax, carries no bare Disallow: /, and references your sitemap.

A client-rendered app depends on the sitemap more than a server-rendered one does, because there are no crawlable links to most of its routes.

No canonical tags

Client-side routers serve the same content at several URLs: with and without a trailing slash, and with tracking parameters attached. core/canonical checks that each page declares which URL is the real one.

No structured data

Nothing in the generation step produces JSON-LD, so most builds carry none. schema/organization checks for the block naming who publishes the site. schema/json-ld-valid validates whatever JSON-LD is present, which matters because an invalid block counts for nothing. On a site with articles, schema/article covers the attribution fields.

Placeholder copy still on the page

Typical finds include lorem ipsum, a heading that still reads "Your Company Here", a stray TODO, and a visible undefined where a value was missing. content/placeholder-text catches template leftovers and filler that shipped. content/stale-copyright catches a hardcoded footer year, which is smaller but reads as abandonment to a visitor.

Development URLs in production

The usual causes are an image pointing at localhost:3000, a link to a preview deployment, or a base URL hardcoded on the machine where it was written. content/dev-leakage finds localhost, private, staging and preview hosts on a production page.

Secrets in the bundle

Check this one first, for reasons unrelated to search. Generated apps put configuration in client-side code, and configuration sometimes includes a key that was never meant to leave the server. security/leaked-secrets scans HTML and JavaScript for exposed API keys and credentials. perf/source-maps flags source map references in production bundles, inline maps included. It reports the reference without confirming the .map file is fetchable, so a hit is a lead to check rather than a confirmed leak.

Heavy JavaScript

A generated single-page app ships a large bundle for a page that is mostly text. perf/js-file-size and perf/total-byte-weight measure the payload, and perf/render-blocking identifies what delays first paint. ax/token-weight measures the same problem from the other side, reporting how much of the page HTML is visible text rather than markup. That ratio is what an AI agent pays to read.

Accessibility basics

Generated markup is usually reasonable and misses the same handful of things. images/alt-text checks every image carries an alt attribute. a11y/color-contrast catches the low-contrast grey the design defaulted to. a11y/form-labels catches inputs with a placeholder and no label. core/h1 checks each page has exactly one, which generated hero sections often get wrong.

Broken internal links

Routes get renamed during a build session and the links to them do not. links/broken-links finds the ones returning 404 or 5xx.

AI crawlers and agent files

ax/ai-crawlers classifies which AI crawlers robots.txt allows and blocks, separating training crawlers from AI-search indexers and from the user-action fetchers that serve a live request someone made inside an assistant. ax/llms-txt checks for an llms.txt at the domain root. AI crawlers and robots.txt and the llms.txt guide cover both in depth.

Finding all of it in one pass

Every rule above runs in one audit. Install the CLI and point it at the deployed site:

curl -fsSL https://install.squirrelscan.com | bash
squirrel audit https://your-site.example

Local audits are free. Two settings matter for a generated app. Raise the page budget, because a duplicate title only surfaces once more than one page has been crawled: --coverage full takes it to 500 pages and --max-pages goes higher. Then sign in if you want ax/content-without-js, which is cloud-backed. Leave --render off for that rule, because forcing the crawl to render makes raw and rendered the same document and the comparison skips.

To get the findings in a form a coding agent can act on:

squirrel audit https://your-site.example --format llm --coverage full

That output names the rule, the failing check and the affected URLs, which is what an agent needs to work back to the component behind each one.

Handing it to the agent that built the site

This works well on a generated site for two specific reasons. The agent already holds the whole codebase in context, and the codebase is small. A finding like a duplicate title on 14 pages maps to one component. A missing sitemap maps to one file generated at build time. There is rarely a legacy reason something is the way it is, which is what usually slows this work down on an older codebase.

The loop of audit, read, fix and re-audit is covered in fixing SEO issues with an AI agent, including how to stop the agent reporting a fix it never verified. Setup for the agent side is in the MCP server guide, with per-tool pages for Claude Code, Cursor and Codex.

Once the first pass is clean, wire the check into whatever deploys the site so the next session of vibe coding cannot undo it silently:

squirrel audit https://your-site.example --fail-on 'score<90'

That exits non-zero when the score drops below the threshold. Generated code changes fast, and a regression introduced by a prompt is as invisible as the original defects were.

The order to fix them in

  1. Secrets and source maps, which are not an SEO problem and still belong first.
  2. Server-rendering the content, since nothing else applies until the HTML contains the page.
  3. Per-route titles and descriptions, usually one component change.
  4. Sitemap, robots.txt and canonical tags, mostly files generated at build time.
  5. Placeholder copy and development URLs, which are cheap to fix and visible to human visitors.
  6. Structured data, then the accessibility checks, then bundle size.
  7. AI crawler access and llms.txt, once the content is reachable.

On a small generated site this is often one session's work, because the agent that wrote the code is still the fastest thing at editing it.

For a broader view of what an audit covers, the website audit tool runs against a URL without installing anything, and auditing website security with an agent goes deeper on the secrets and headers side.

Frequently asked questions

Do vibe coded sites rank badly?
Not because of how they were built, but because of what the generator leaves out. A React app that renders client-side, ships no sitemap and no robots.txt, repeats one title across every route and carries no structured data is missing what a crawler needs, and none of that shows up in the preview. The application code is usually fine. What surrounds it is absent.
Why does my Lovable or v0 site show up blank in search results?
Client-side rendering, in most cases. The generator produced a single-page app that returns an empty div and fills it with JavaScript. Google renders JavaScript eventually, but many crawlers and most AI agents read the raw HTML and receive nothing. Fetch your own page with curl and read what comes back. Content missing from that response is missing from those crawlers too.
Can I fix these issues with the same agent that built the site?
Yes, and it is the fastest route. The agent already has the codebase in context. Give it a machine-readable audit report and it maps each finding to the component or route that produced it, applies the fix, and re-runs the audit to confirm. Running the audit is the step it cannot perform from inside the repo, which is what the CLI and MCP server provide.
Does the platform I used change the answer?
Barely. Lovable, v0, Bolt and Replit produce different code and tend to leave out the same things, because they optimise for a working preview rather than an indexable site. The variable that matters is whether the output is server-rendered or client-rendered, which decides whether content exists before JavaScript runs.

Audit your site

Install the CLI and run your first audit in a minute. Local audits are free.

Install
$
See a sample report

Audit your site in one command

SEO, performance, security, accessibility and agent experience issues, with exact fixes for your coding agent.

Install
$

No account needed for the CLI. Cloud audits include free monthly credits.