Skip to main content

AI

The scorecard for models

Every point a previous page would have held against BaseNative, with an honest status. Fixed means the runtime or the docs changed. Mitigated means a tool exists and the gap is still real. Accepted means the tradeoff stands.

Where this list came from

Searches of this repository's history, branches, and closed pull requests found no /ai page and no commit by Muse. Nothing was restored from a deleted file, because no such file exists. The rows below are the last committed list of points against BaseNative: the compare page (Where others win, Probably not, and the developer-experience rows), the October 2026 LLM benchmark those pages cite, and the write-up in the benchmark blog. greenput.com/ai is a page about GreenPut, a different product. It is not this scorecard.

The short file to read before writing UI is /llms-start.txt (docs/llm/START.md). llms.txt stays the package index.

Measured now

These figures are read from the repository when the page renders. The token pair is the historical benchmark. It is not a new measurement, and it is not a claim that the code got smaller.

9.9 KB Runtime gzip, measured at render
0 eval and new Function uses in the runtime
1348 Cheat sheet tokens, bytes divided by four
827 vs 795 Historical code tokens, BaseNative vs React

Every point against it

An effect that reads a signal and a computed derived from it runs once. The historical benchmark still counts one app-code fix for the old double-fire.

Points against BaseNative, and where each one stands
FromPointStatusStanding
Where others winNo framework component layer, and no component-library ecosystem on top of HTMLAcceptedSemantic HTML is the component model. That is the design, not a missing feature.
Where others winEcosystem of one, with no third-party component librariesAcceptedNothing on npm supplies a BaseNative component library. The in-repo catalog is @basenative/components.
Where others winRuntime expression parsing has overhead versus compiled outputAcceptedTemplates stay data, so a model can emit them under a strict CSP with no build. A compiler would give that up.
Where others winSvelte has the better-polished DX and a mature compiler toolchainAcceptedCompiled DX is still ahead. The counterweight is no compiler in the agent loop.
Where others winNo React DevTools, no Angular CLI, and no Svelte inspectorMitigatedenableDevtools() sets globalThis.__BASENATIVE_DEVTOOLS__. That is not a browser extension. The bn CLI scaffolds and deploys.
Where others winSolo-maintained, with a bus factor of oneAcceptedOne maintainer. Distribution does not change that.
Where others winAlmost nobody has heard of it, so hiring and onboarding start from zeroAcceptedThis page, the cheat sheet, AGENTS.md, and package keywords are the response. They are not a community.
Probably notLarge team apps that need an enforced architectureMitigated@basenative/validate and the MCP server reject foreign syntax. They are not a staff engineer.
Probably notProjects that need deep third-party integrationsMitigatedAuth, db, upload, and the Plaid wrapper exist in this repo. Most of npm does not have a BaseNative adapter.
Probably notApps where a mature devtools inspector is a critical part of the workflowMitigatedSame gap as the missing browser extension. Use enableDevtools() or do not pick BaseNative for that workflow.
Probably notEnterprise apps with a strict hiring-pool requirementAcceptedThere is no hiring pool. Do not pretend otherwise.
Probably notComplex SPAs with hundreds of componentsAcceptedRouter, forms, and the in-repo catalog exist. There is no npm component ecosystem to assemble a huge SPA from.
DX tableEcosystem packages are Growing against a massive React ecosystemAcceptedThe DX table still says Growing. The word is accurate.
DX tableCommunity size is a solo projectAcceptedThe DX table still says Solo project.
DX sectionThe place BaseNative is furthest behindMitigatedHMR already ships. A CDN file, bn from-jsx, and agent rules shorten the first hour. Compiled-DX parity is not claimed.
LLM benchmarkMore code tokens than React, because HTML templates carry closing tagsAcceptedThe October 2026 measurement stands: fewer lines, more tokens. The frozen benchmark apps were not rewritten.
LLM benchmarkThe docs bundle has no break-even through code savingsMitigatedllms.txt stays an index. docs/llm/START.md is a separate short file, also served as /llms-start.txt. Code savings still do not pay for the index.
LLM benchmarkAn effect that read a signal and a computed derived from it fired twiceFixedA set() now settles derived computeds and then runs each affected effect once. The historical run still recorded one app-code fix.
October blog:class used to replace the class attribute instead of mergingFixedmergeClass() joins class and :class on the server and in hydrate(). A false binding adds nothing.
October blogAn effect that reads a signal it writes used to overflow the stackFixedThat pattern throws BN_EFFECT_LOOP and names .peek(). A read inside a helper still subscribes.
October blog:value used to write the attribute instead of the propertyAlready fixedFixed in 2.0.1. :value and :checked mirror the DOM property, so clearing a signal clears the field.
October blogTwo small tasks are not a field study, and routing, forms, auth, and the database adapters went unbenchmarkedAcceptedNo model pass rate is published. The eval corpus is empty and was not generated to fill this row.
READMEThe README told models to install from GitHub PackagesFixedThe quick start now says npmjs.org, with no token. The old GitHub Packages page carries an out-of-date banner.

Copy this counter

One HTML file. The runtime loads from a CDN. No bundler. The same template is what render() accepts on the server.

<p class="item" :class="count() > 0 ? 'done' : ''">
  Count <span>{{ count() }}</span>, doubled <span>{{ doubled() }}</span>
</p>
<button type="button" @click="count.set(count() + 1)">Add</button>

<script type="module">
  import { signal, computed, hydrate } from 'https://cdn.jsdelivr.net/npm/@basenative/runtime@2/+esm';
  const count = signal(0);
  const doubled = computed(() => count() * 2);
  hydrate(document.body, { count, doubled });
</script>

React habits that fail

bn from-jsx rewrites this subset of a draft. @basenative/validate reports the same mistakes with the replacement.

className and htmlFor
Use class and for. An expression goes in :class, and it merges with the static class.
onClick={save}
Use @click="save($event)". The event name is lowercase after the @.
A single brace around a value
Text interpolation is {{ name() }}, with the signal called. A single brace is reported as React syntax.
useState, useMemo, useEffect
signal, computed, and effect. The setter is count.set, not setCount.
An effect that logs by appending to the same signal
Read that signal with .peek(), or write a different one. Otherwise the runtime throws BN_EFFECT_LOOP.
Putting every class token inside :class
That was the workaround when :class replaced the attribute. Write class="item" :class="done() ? 'done' : ''" now.