benchmarks
BuilderProof editorial team19 min read8 views

Does It Run in the Browser They Actually Have? A Proposed Browser-Support Axis for AI App Builder Output (September 2026)

A proposed benchmark axis for which browser engines a generated app can actually run in. Baseline defines widely available as 30 months of interoperability and names what it cannot see. Next.js floors at Firefox 111, Vite resolves its default to Firefox 114, and the preview pane reports a pass either way. Seven weighted signals, four postures, a ten-step protocol, and no scores.

Updated on September 21, 2026

Flat editorial line diagram on a pale background: five small outlined rounded rectangles in a row, each with a thin bar across its top edge like a browser window, the first four containing an identical small dark dot and the fifth left completely empty.
Flat editorial line diagram on a pale background: five small outlined rounded rectangles in a row, each with a thin bar across its top edge like a browser window, the first four containing an identical small dark dot and the fifth left completely empty.
On this page

Quick Answer

Browser-support posture is a proposed BuilderProof benchmark axis, drafted September 21, 2026, that measures which browser engines the application an AI app builder emits can actually run in, and whether anybody involved knows. It is scored from the untouched export: the target the project states, the versions that target resolves to, the date it resolves against, and what happens in an engine that is inside the stated floor but is not the one the preview pane uses. This page is a pre-registration rather than a report. It publishes a rubric and a protocol before any builder is measured against them, and it assigns no score to any vendor.

The problem this axis exists for

An AI app builder is a very good witness to one question: does this work in the browser that is showing it to me right now. The preview pane renders. You open the deployed URL in your own browser and it renders there too. You send the link to a colleague who opens it in the same browser on the same kind of laptop, and it renders for them.

Every one of those observations came from the same engine, and it is the newest one. The preview pane is a current Chromium. The machine you are building on is running a browser that updates itself silently every few weeks. Nothing in that loop is capable of telling you that the application uses an API which the oldest browser in its own stated support floor does not have, or that a phone two operating system versions behind renders a blank page.

This is not a hypothetical class of defect. It is the ordinary consequence of a build pipeline that makes a decision on your behalf, records that decision in a config file nobody reads, and produces output that is correct against that decision and silent about it.

What "browser-support posture" means here

For this axis, browser-support posture is the degree to which the emitted application has a stated, resolvable, and exercised floor for the engines it runs in. Three words are load-bearing.

Stated. The floor exists whether or not anyone wrote it down, because the toolchain has a default. Stating it is a separate act from having it.

Resolvable. A target expressed as a tool keyword is not yet a floor. It becomes one when it has been resolved to concrete engine versions, with the date it resolves against.

Exercised. A floor that has never been run against is a claim. The axis reserves its top posture for a floor somebody has actually opened the application in.

Where the floor comes from, in the vendors' own words

The floor is decided at three layers, and each layer documents itself correctly while none documents the composition.

WebDX Community Group The standard. Baseline is the shared vocabulary the rest of the stack now points at. web.dev's Baseline page sets out two stages. Verbatim: "Newly available: The feature is supported by all of the core browsers, and is therefore interoperable." and "Widely available: 30 months have passed since the newly interoperable date. The feature can be used by most sites without worrying about support." The core browser set is named explicitly: Chrome on desktop and Android, Edge, Firefox on desktop and Android, and Safari on macOS and iOS. The same page records that Baseline "was originated by the Chrome team and is now defined by the WebDX Community Group".

MDN The standard's own limits. MDN's Baseline glossary entry states the same two stages in different words, and then does something unusually useful: it says what Baseline cannot tell you. Verbatim: "Baseline is a summary of browser support. It is not a substitute for accessibility, usability, performance, security, or other testing. Baseline may not tell you if a feature works with: Older devices and browser releases; Browsers not covered by the Baseline definition, such as operating system web views; Assistive technology, such as screen readers." That middle item is the one worth sitting with. An in-app browser inside a social or messaging application is an operating system web view, it is a large share of real mobile traffic for a link somebody shares, and it is outside the set the standard considers.

The two phrasings of the widely-available threshold reconcile exactly. web.dev gives 30 months, MDN gives "at least 2.5 years", and 30 divided by 12 is 2.5. That is worth checking rather than assuming, because the two pages are the sources a rubric would anchor to and a rubric built on two numbers that disagreed would be measuring the disagreement.

Vercel The framework. Next.js documents a hard floor, last updated July 28, 2026: Chrome 111 and above, Edge 111 and above, Firefox 111 and above, Safari 16.4 and above, expressed as a default Browserslist configuration of chrome 111, edge 111, firefox 111, safari 16.4. It injects three named polyfills, for fetch(), URL and Object.assign(), and it is candid about where that stops. Verbatim: "If your own code or any external npm dependencies require features not supported by your target browsers (such as IE 11), you need to add polyfills yourself."

Vite The build tool. Vite's build.target defaults to a special value, and its documentation resolves it for you. Verbatim: "The default value is a Vite special value, 'baseline-widely-available', which targets the minimum browser versions compatible with Baseline Widely Available as of a date fixed for each major release (2026-01-01 for this major). Specifically, it is ['chrome111', 'edge111', 'firefox114', 'safari16.4', 'ios16.4']." The page also notes that the build "will output a warning if the code contains features that cannot be safely transpiled".

Browserslist The shared configuration layer. Both of the above speak Browserslist. Its README documents that when nothing else produces a result, defaults applies, and that defaults resolves to a union of four queries: a usage share above 0.5 percent, the last 2 versions of each browser, Firefox ESR, and not dead. It has since added Baseline queries, including baseline widely available on YYYY-MM-DD for pinning to a date and a with downstream modifier that, in its own words, "includes browsers outside the core browser set that support the requested Baseline feature set based on their Chromium or Gecko version".

Two toolchains, two floors, and nobody says which one you got

Put the framework and the build tool side by side on the one thing they both claim to answer.

Scroll to see more

LayerChromeEdgeFirefoxSafariiOS Safari
Next.js default Browserslist11111111116.4not named separately
Vite baseline-widely-available (2026 major)11111111416.416.4

Four of the five columns agree. Firefox does not, and the gap is three major versions. Vite additionally names an iOS Safari entry, where the Next.js default list does not carry one as a separate Browserslist browser.

Neither number is wrong. They are answering slightly different questions on slightly different dates, which is exactly the point: an application generated on one toolchain and an application generated on the other have measurably different browser floors, and neither generator tells the person who asked for the app which one they got. A benchmark that only ever asks "does the generated app work" cannot see this, because on the machine doing the asking both answers are yes.

The second sentence of Vite's own definition is the more consequential half. The floor is fixed "as of a date fixed for each major release". It does not track Baseline over time. It moves when, and only when, the build tool's major version moves.

The tension with stack currency, stated rather than resolved

That has a direct consequence for an axis we already propose. Our stack-currency axis rewards a documented stack sitting on a currently-supported major version, anchored to the upstream project's own end-of-life calendar. It says of itself that it "is not a freshness race", which is fair, and it is still the case that the action which raises a stack-currency score is upgrading a major.

Upgrading that major is the same action that raises the browser floor. The user's engine has no end-of-life calendar we control, and the user does not upgrade on our schedule. So the two axes can be pushed in opposite directions by one commit, and neither of them can see that on its own.

We are not proposing to resolve this by choosing. The resolution is ordering and disclosure: a stack upgrade is still the right default, and the floor it moves should be re-derived and republished at the same time rather than discovered later by somebody on an older phone. Scoring that re-derivation is signal 9 in the protocol below.

What this axis is not

It is not responsive-layout posture. Our responsive-layout axis asks whether the emitted layout reflows across viewport widths. Its harness renders "in headless Chromium device emulation at 320, 375, 414, 768, 1024, and 1440 CSS pixels". It varies the size of the window and holds the engine fixed, by construction, and it says so. This axis does the reverse: it holds the window fixed and varies the engine. Both directions are real. A layout can reflow perfectly at 320 pixels in Chromium and render nothing at all in an engine that lacks the CSS feature the reflow is built on, scoring at the top of that axis and the bottom of this one. An application can use only decade-old CSS, running everywhere, and still have no mobile breakpoint, scoring the reverse.

It is not crawler-facing metadata. Our generated-app SEO and meta output axis weights "content of every indexable route present in the HTML served to a crawler user agent, without JavaScript execution" at 25, its heaviest signal. That is a question about a client which deliberately does not execute the script. This one is a question about a client which tries to execute the script and cannot. They come apart in both directions. A fully server-rendered page satisfies that signal and can still throw during hydration in an in-floor Safari, leaving a rendered page that does nothing when touched. A client-only application can run flawlessly in every engine on earth and still serve a crawler an empty body.

It is not client network failure handling. Our client network failure axis asks what the application does when the request does not complete. Here the request completes perfectly, the bytes arrive intact, and the engine cannot run them. Same visible outcome for the user, different cause, and the remedies do not overlap at all.

It is not type safety. Compile-time checking asks whether the code is internally consistent against the types it declares. A build can typecheck cleanly against a library declaration for an API and then ship that API to an engine which does not implement it, because a type declaration is a statement about what the compiler believes, not about what the engine has.

The gap a neighbour already recorded

We are not the first page on this site to notice the problem. Our URL-state addressability proposal lists among its own limitations, verbatim: "Restoration eligibility is browser-dependent, and the documentation says so. Chrome and Safari do not block on open sockets where other engines do. A single-engine probe will therefore report an eligibility that is not general, and the honest options are to name the engine with the score or to probe more than one. We currently favour naming the engine."

That is an accurate description of a blind spot and a reasonable decision about what to do inside that proposal. It is also an admission that the engine is a free variable in our own harness, currently held constant and disclosed rather than measured. This axis is the proposal to measure it once, in one place, so that the other axes can keep naming their engine and point here for what that engine choice costs.

The proposed rubric

Seven signals, weighted to total 100. Weights are a proposal and are the part we most want argued with.

Scroll to see more

SignalWeightWhat a failing case looks like
A browser floor is stated in the emitted project22Nothing in the export names a target. The floor is whatever the toolchain defaulted to on the day the app was generated, and reading it requires knowing which tool to ask.
Syntax and runtime APIs are handled as separate problems20The bundle is transpiled down correctly and then calls an API the oldest in-floor engine does not implement, because downlevelling syntax is not the same act as providing a missing API.
The stated floor is resolved to versions, with a date16The config says a keyword. Nobody in the loop can say which engine versions that keyword resolves to, or as of when, and the keyword's own meaning is pinned to a release date rather than to today.
Something outside the core browser set is considered14The floor names four desktop engines. The product's real traffic arrives through a link opened inside an application's own web view, which the standard's own documentation excludes from its definition.
A non-Chromium engine has been opened at least once12Every observation of whether this application works was produced by the preview pane and one desktop Chromium, both current, both updating themselves.
Feature adoption is checked against the stated floor9A newly available API is used because it worked when it was tried, with no check against the floor the project claims to support.
Failure in an unsupported engine is visible rather than silent7An engine that cannot parse a chunk produces a blank page and no surface anywhere reports it, so the only evidence the defect exists is a user who does not come back.

Two deliberate choices. Stating the floor carries the most weight even though it is the cheapest of the seven, because it is the only one that is strictly a precondition: none of the other six is well defined until there is a floor to measure against. And syntax versus API is weighted second because it is the failure that survives a correct build: the transpiler did its job, the warning Vite documents did not fire, and the application still breaks.

Four postures

Scroll to see more

LevelNameWhat it means
0InheritedNo target is stated anywhere in the export. A floor exists, because the toolchain has a default, but it is an accident of which tool version generated the app.
1StatedThe project names a target and it can be read out of the repository without knowing the toolchain's internals.
2ResolvedThe stated target has been resolved to concrete engine versions and dated, and syntax handling is distinguished from API availability.
3ExercisedThe resolved floor has been opened at least once in a non-Chromium engine and once in an out-of-set surface, and a failure in either is visible rather than silent.

The step from 0 to 1 is the only one an operator can take with no new tooling and no new information: the floor already exists, and stating it is a matter of writing down what the toolchain already decided. The step from 2 to 3 is the only one that produces evidence rather than a claim, and it is the step the preview pane structurally cannot help with.

The reproduction protocol

  1. One fixed brief, cold generation. Generate once in a fresh session, with no follow-up prompts. We are measuring the default emission, not what the tool can do when coached.
  2. Untouched export. Take the exported code as-is and build it with the project's own build command. No hand edits, no added configuration.
  3. The looks-correct control. Serve the build and open it in a current Chromium. Confirm it works. Everything after this step is measured against a working application, and skipping it makes every later failure unattributable.
  4. Read the floor out of the repository. Record what each of these says, and whether they agree with each other: a browserslist field or file, the bundler's target option, the compiler's target and library settings, and any framework configuration. Disagreement between two of them is itself a finding.
  5. Resolve the floor. Where the configuration uses a keyword or a Baseline query, record the concrete version list it resolves to and the date it resolves against. Publish both, because a floor without its date is not reproducible six months later.
  6. Separate syntax from APIs. Scan the built bundle for syntax the floor forbids, then separately for runtime APIs newer than the floor. A bundle can be clean on the first scan and fail on the second, and conflating them is the commonest way this defect is missed.
  7. Open it in the oldest in-floor non-Chromium engine. This is the step the preview pane cannot perform, and the first point in the protocol at which a new fact can appear.
  8. Open it in one out-of-set surface, an operating system web view, and record the result separately rather than folding it into the score, since the standard excludes it by definition.
  9. Upgrade one major and re-derive. Change nothing else, bump the build tool or framework major, and re-run steps 4 and 5. Record whether the floor moved and whether anything in the project announced that it had. This is where the stack-currency tension becomes a measurement instead of an argument.
  10. Publish the resolved floor, the date, the engines exercised and every failure, per builder, alongside the raw configuration files read in step 4.

The preview-pane illusion

The failure this axis exists to catch is hidden by the instrument everybody uses to look for it. The preview pane is a single engine. It is always the newest one, it updates without being asked, and it is the same engine as the browser the person prompting the builder is almost certainly using. Every observation available at the moment of building is generated by that one actor.

So the application is not merely untested in other engines. It is untestable in them by the means at hand, and the means at hand return a clean result every time. A green preview is not weak evidence about browser support. It is not evidence about browser support at all, because the variable it would have to vary is the one thing it holds fixed.

There is a second turn to it. The three layers above each behave correctly and each document themselves accurately. Baseline says what it covers and lists what it does not. Next.js names its floor and says where its polyfills stop. Vite resolves its keyword and dates it. Nobody is hiding anything. The gap is that no document describes the composition, and the composition is what the user's phone meets.

What we are not claiming yet

No scores today. This page proposes the axis, the rubric, the postures and the method; it does not rank anyone. We have read platform documentation, one framework's documentation, one build tool's documentation and one configuration library's documentation, and no builder output. Nothing here should be read as a measurement of v0, Lovable, Bolt, Replit or Base44, and the postures described are structural rather than observed.

Limitations and open questions

  • We have read documentation and no generated application. That is a deliberate scope choice for an axis proposal and it is also the largest gap on this page. Every posture above is a structure, not a result.
  • The out-of-set probe in step 8 is the weakest part of the protocol. Operating system web views vary by operating system version and by host application, there is no published set to fix, and two people running this step will not run it against the same thing. Until that is pinned, the result should be published beside the score rather than folded into it.
  • Much of the floor is inherited from the framework rather than authored by the generator. Two builders emitting onto the same framework will score nearly identically on the first three signals, which says very little about either. This is the same problem our pagination and URL-state proposals both record about inherited primitives, and we do not have a better answer here than reporting inherited and authored behaviour separately.
  • Step 7 may not be performable for the oldest in-floor version. Obtaining and running a specific older Safari on current hardware is a practical obstacle rather than a methodological one, and a protocol that quietly substitutes the newest available version of a non-Chromium engine is measuring something weaker than it claims.
  • Signal 7 overlaps error-message debuggability. The boundary we intend is that the other axis asks whether an error, once raised, is legible. This one asks whether an engine-level failure raises anything at all. Whether that boundary survives contact with real scoring is unresolved.
  • Widely available or newly available. A rubric anchored to Widely available is 30 months behind the platform and will mark down an application for using something that has worked everywhere for two years. One anchored to Newly available marks down almost nobody. We currently lean to Widely available for the floor and Newly available for signal 6, and we are not confident.
  • Opt-in legacy builds. Tooling exists to emit a second, downlevelled bundle for older engines. Crediting it without rewarding a heavier bundle for every modern visitor needs a weighting we have not worked out.

Counter-rubrics, corrections and reproduction attempts are welcome. The most useful thing anyone can send us is the output of step 5 against a project of their own: the resolved version list, the date it resolved against, and which file in the export it came from. A rubric is easiest to correct before it has ever produced a score.

References

Cite this benchmark

Plain text
BuilderProof editorial team. "Does It Run in the Browser They Actually Have? A Proposed Browser-Support Axis for AI App Builder Output (September 2026)". BuilderProof, September 2026. https://www.builderproof.org/benchmarks/does-it-run-in-the-browser-they-actually-have-browser-support-axis-september-2026.
BibTeX
@misc{builderproof-does-it-run-in-the-browser-they-actually-have-browser-support-axis-september-2026,
  title  = {{Does It Run in the Browser They Actually Have? A Proposed Browser-Support Axis for AI App Builder Output (September 2026)}},
  author = {{BuilderProof editorial team}},
  year   = {2026},
  month  = {sep},
  howpublished = {\url{https://www.builderproof.org/benchmarks/does-it-run-in-the-browser-they-actually-have-browser-support-axis-september-2026}},
  note   = {BuilderProof, builderproof.org}
}

Frequently asked questions

What is browser-support posture for an AI app builder?

It is a proposed BuilderProof benchmark axis, drafted September 21, 2026, that scores whether the application a builder emits has a stated, resolvable and exercised floor for the browser engines it runs in. It is read from the untouched export: the target the project states, the engine versions that target resolves to, the date it resolves against, and what happens in an engine inside that floor which is not the one the preview pane uses. It is a pre-registration, and it scores no vendor.

Is this not the same as the responsive-layout axis?

No, and the two are near-exact complements. The responsive-layout harness renders in headless Chromium device emulation at 320, 375, 414, 768, 1024 and 1440 CSS pixels: it varies the size of the window and holds the engine fixed. This axis holds the window fixed and varies the engine. A layout can reflow perfectly at 320 pixels in Chromium and render nothing in an engine that lacks the CSS feature the reflow depends on, and an application can use only decade-old CSS that runs everywhere while having no mobile breakpoint at all.

Why does the browser floor differ between build toolchains?

Because each toolchain picks its own default and dates it differently. Next.js documents a default Browserslist configuration of chrome 111, edge 111, firefox 111 and safari 16.4. Vite defaults build.target to the special value baseline-widely-available, which its documentation resolves to chrome111, edge111, firefox114, safari16.4 and ios16.4 as of a date fixed per major release. Four of the five entries agree and Firefox differs by three majors. Neither number is wrong, and neither generator tells the person who asked for the app which one they received.

What is the preview-pane illusion?

It is the failure mode this axis exists to catch. Every observation available while an application is being built comes from one engine: the builder's preview pane, and the browser of the person prompting it, both current Chromium and both updating silently. The application is therefore not merely untested in other engines, it is untestable in them by the means at hand, and those means return a clean result every time. A green preview is not weak evidence about browser support, it is not evidence about browser support at all, because the variable it would have to vary is the one it holds fixed.

Methodology

Generated-App SEO and Meta Output Quality: A Proposed Axis for What AI App Builders Actually Emit to Crawlers (August 2026)

A candidate BuilderProof benchmark axis that scores the crawler-facing artifacts AI app builders emit by default: per-route titles, canonicals, social cards, robots.txt, sitemap.xml, structured data, and whether route content reaches a crawler at all. Rubric, four rendering postures found in the vendor docs, a dual user-agent reproduction protocol, and an open call for comment.

17 min read106