A signal-based web runtime over native HTML — zero build step, zero production dependencies.
BaseNative makes the browser's own primitives the component model. A <template> element is the component. A {{ }} interpolation is the binding. signal() is the state. No JSX, no virtual DOM, no namespace theater.
| Problem | BaseNative |
|---|---|
| Frameworks ship 50-300KB of runtime | Core runtime is < 5KB gzipped |
| Build pipelines break, lock you in | No build step — <script type="module"> is enough |
| JSX/template syntax is proprietary | Standard HTML — any LLM reads it in zero shots |
| State is tangled across multiple files | Trinity Standard — state + logic + template in one file |
| CSS-in-JS pollutes markup | Zero inline styles — cascade layers only |
npm install @basenative/runtime @basenative/serverServer (Node.js / Cloudflare Workers):
import { render } from '@basenative/server';
const html = render(`
<h1>{{ title }}</h1>
<template @if="user">
<p>Welcome, {{ user.name }}!</p>
</template>
<template @else>
<p><a href="/login">Sign in</a></p>
</template>
<ul>
<template @for="item of items; track item.id">
<li>{{ item.name }}</li>
</template>
</ul>
`, { title: 'Dashboard', user: { name: 'Alice' }, items });Client (browser):
import { signal, computed, effect, hydrate } from '@basenative/runtime';
const count = signal(0);
const doubled = computed(() => count() * 2);
effect(() => console.log(`${count()} → ${doubled()}`));
hydrate(document.getElementById('app'), { count, doubled });| Package | Description |
|---|---|
@basenative/runtime |
Signals, computed, effects, hydration, lazy loading, Web Vitals |
@basenative/server |
SSR — render(), streaming, hydration markers |
@basenative/router |
SSR-aware routing with params, wildcards, query helpers |
@basenative/forms |
Signal-based field state, validators, Zod adapter |
@basenative/components |
15 semantic UI components with design token theming |
@basenative/auth |
Session management, RBAC, password hashing, OAuth providers |
@basenative/db |
Query builder + SQLite/PostgreSQL/D1 adapters |
@basenative/middleware |
Pipeline, CORS, rate-limit, CSRF — Hono/Fastify/CF Workers adapters |
@basenative/config |
Env loading, type-safe schema validation |
@basenative/logger |
Structured logging, multiple transports, child loggers |
@basenative/fetch |
Signal-based resource fetching with SSR preload and cache |
@basenative/i18n |
ICU message formatting, locale detection, @t directive |
@basenative/realtime |
SSE + WebSocket with reactive channel management |
@basenative/tenant |
Multi-tenant middleware — subdomain, path, header resolvers |
@basenative/upload |
Multipart upload with R2/S3 storage adapters |
@basenative/notify |
Email templates + SMTP/SendGrid transports |
@basenative/flags |
Feature flags with percentage rollouts and user context |
@basenative/date |
Date utilities, formatting, calendar generation |
@basenative/cli |
create-basenative scaffolding and bn dev commands |
@basenative/fonts |
Font loading utilities |
@basenative/icons |
Icon system |
@basenative/marketplace |
Community component registry |
@basenative/visual-builder |
No-code template builder |
<!-- Interpolation -->
<p>Hello, {{ user.name }}!</p>
<!-- Conditional -->
<template @if="isAdmin"><button>Delete</button></template>
<template @else><span>Read-only</span></template>
<!-- Lists with keyed reconciliation -->
<template @for="item of items; track item.id">
<li>{{ item.name }}</li>
</template>
<template @empty><p>No items.</p></template>
<!-- Switch/case -->
<template @switch="role">
<template @case="'admin'"><AdminPanel /></template>
<template @case="'editor'"><EditorTools /></template>
<template @default><ViewerMode /></template>
</template>
<!-- Dynamic attributes -->
<input :disabled="!canEdit" :class="isActive ? 'active' : ''">BaseNative never calls eval or new Function. The expression evaluator supports a deliberate safe subset: property access, method calls, arithmetic, comparison, logical operators, ternary, array/object literals. Move complex logic into named functions in your context object.
Template (HTML)
↓ @basenative/server (Node / Workers)
Rendered HTML + <!--bn:*--> markers
↓ @basenative/runtime (browser)
Hydrated DOM with live signal bindings
↓ signal updates
Targeted DOM patches (no full re-render)
Current evergreen browsers: Chrome, Edge, Firefox, Safari.
pnpm install
node --test # tests in any package directory
npx nx run-many --target=test --all # all packages via Nx
npx nx run-many --target=lint --all| Example | Description |
|---|---|
examples/express |
Full Express app with components showcase |
examples/cloudflare-workers |
Cloudflare Workers with SSR + routing |
examples/node |
Standalone Node.js HTTP server |
examples/enterprise |
Auth + DB + middleware stack |
examples/enterprise-v2 |
Multi-tenant enterprise patterns |
| Guide | Description |
|---|---|
| Getting Started | Install, first component, routing, SSR |
| Building a Todo App | End-to-end tutorial: SSR + signals + forms + flags |
| API Reference | Full API docs for all 23 packages |
| Migration Guide | Moving from React, Vue, Svelte, or vanilla JS |
| Accessibility | ARIA, keyboard nav, screen reader support |
| Browser Support | Supported browsers and polyfill guidance |
| Roadmap | Upcoming features and milestones |
| Release Process | How versions are cut and published |
See CONTRIBUTING.md. Contributions welcome — open an issue first for significant changes. Built on conventional commits with Changesets for versioning.
See SECURITY.md for the security policy and how to report vulnerabilities.
Apache 2.0 — see LICENSE.