Skip to content
K

Lit

Naos vs. Lit — compiler with signals vs. runtime library with templates.

Naos and Lit

Lit is the default way most teams build Web Components today: a small, mature runtime library from Google. Naos targets the same output — native Custom Elements — but gets there as a compiler rather than a runtime library, and with JSX and signals instead of tagged template literals and reactive properties.

Positioning snapshot from July 2026. Naos is a v0.1 prerelease; Lit is a mature, widely deployed library. This page explains where Naos fits, not a ranking of a mature project against an MVP.

At a glance

NaosLit
One-line pitchTSX compiler for native interface elementsSimple, fast library for building Web Components
KindCompiler — output is generated per elementRuntime library — shipped with your components
Output targetNative Custom Elements, Shadow DOM, slots, part, DSD, form-associatedNative Custom Elements, Shadow DOM, slots, part
TemplatingJSX / TSX compiled to direct DOM codehtml tagged template literals (lit-html)
Authoring unitExported PascalCase functionsClasses extending LitElement (+ decorators)
ReactivityExplicit signals: state(), computed(), effect()Reactive properties (@property / @state) trigger re-render
Virtual DOMNoneNone (lit-html template diffing)
Runtime costSmall shared, tree-shakeable execution kernel; no template or framework runtimeSmall shared runtime (~5 KB) + your components
Build stepRequired (Vite plugin / CLI)Optional — works with plain JS + templates
BatteriesOptional layer: primitives, router, data, motionLabs packages (context, task, ssr, virtualizer) + broad ecosystem
Maturityv0.1 prereleaseMature, production

Common ground

  • The output is the same category: standards-based Custom Elements with Shadow DOM, slots, and part-based styling.
  • No virtual DOM. Lit diffs templates via lit-html; Naos generates direct DOM updates. Both avoid a React-style VDOM.
  • Both prize a small footprint and framework-neutral distribution.
  • Both offer SSR paths (Lit's @lit-labs/ssr; Naos's Declarative Shadow DOM prerender + hydration).

Where they diverge

Compiler vs. runtime library — the core split

Lit is a runtime library. Your components extend LitElement, and the Lit runtime (reactive-update lifecycle + lit-html) is shipped to the browser alongside them. A key upside: no build step is required — you can author Lit with plain JavaScript and template literals.

Naos is a compiler. Components are compiled ahead of time to direct custom-element code; there is no template/reactivity library to ship. The trade is the mirror image of Lit's: you need a build step (the Vite plugin or CLI), and in return there is little to no framework runtime in the output.

Templating and reactivity

  • Lit uses html tagged template literals and reactive properties: changing a @property or @state schedules a re-render, and lit-html efficiently updates the changed template parts.
  • Naos uses JSX/TSX and signals: state(), computed(), effect(). Reads happen by calling the signal (count()); updates touch only the exact bindings that depend on it, with no component-level re-render.

Authoring unit

  • Lit: classes extending LitElement, typically with decorators.
  • Naos: exported PascalCase functions; the function name becomes the tag.

Implementation

Lit's engine is JavaScript. Naos owns compiler semantics in Rust / OXC and keeps the TypeScript packages thin.

Side by side

Naos — a function compiled to a Custom Element:

import { state } from "@naos-ui/core"

export function Counter() {
  const count = state(0)
  return (
    <button part="button" onClick={() => count.set(count() + 1)}>
      Count: {count()}
    </button>
  )
}

Lit — a LitElement class with a tagged-template render():

import { LitElement, html } from "lit"
import { customElement, state } from "lit/decorators.js"

@customElement("my-counter")
export class MyCounter extends LitElement {
  @state() count = 0

  render() {
    return html`
      <button part="button" @click=${() => this.count++}>
        Count: ${this.count}
      </button>
    `
  }
}

Which one fits

Reach for Lit when:

  • you want the mainstream, battle-tested Web Components library with a huge ecosystem and Google backing
  • you value no required build step — author with plain JS and templates
  • tagged template literals and reactive properties suit your team better than JSX and signals
  • you want the safest, most documented path for framework-agnostic components today

Reach for Naos when:

  • you want a compiler that ships no template/reactivity runtime in the output
  • you prefer JSX/TSX + signals and function components
  • you want Declarative Shadow DOM and form-associated output as first-class compiler concerns
  • a Rust/OXC compiler core and a narrow, statically analyzable surface appeal to you
  • you are comfortable adopting a v0.1 prerelease, and a required build step

Honest caveats

  • Naos is a v0.1 prerelease; Lit is mature and production-proven. This is a direction comparison, not a readiness one.
  • "No runtime library" does not automatically mean smaller in every app — Lit's runtime is shared across all its components, which amortizes well at scale.
  • Treat this as a July 2026 snapshot and re-check both projects' current docs.

Sources