Skip to content
K

Solid

Naos vs. Solid — shared signal DNA, different output boundary.

Naos and Solid

Solid is where Naos's reactivity comes from. Naos's state(), computed(), and effect() are signals in the Solid lineage: read by calling, fine-grained, no re-render, no virtual DOM. If any comparison on this site is a family resemblance rather than a coincidence, it is this one.

The divergence is the output boundary: Solid renders an application into a container; Naos compiles each component into a native Custom Element.

Positioning snapshot from July 2026. Naos is a v0.1 prerelease; Solid is a mature reactive library with a full meta-framework around it. This page explains where Naos fits, not a ranking of a mature project against an MVP.

At a glance

NaosSolid
One-line pitchTSX compiler for native interface elementsSimple, performant reactivity for building UIs
ReactivitySignals: state(), computed(), effect()Signals: createSignal, createMemo, createEffect
Virtual DOMNoneNone
Runtime modelSmall shared, tree-shakeable execution kernel; no framework runtimeSmall reactive runtime shared by the app
JSXCompiled to direct DOM codeCompiled to direct DOM code (dom-expressions)
Default outputNative Custom Element per componentApp rendered into a container (render(App, root))
Custom elementsThe primary, built-in outputAvailable via the separate solid-element wrapper
Shadow DOM / slots / partFirst-class in generated elementsThrough solid-element (Shadow DOM), not the default model
CompilerRust / OXC over an N-API boundaryBabel-based JSX transform
BatteriesOptional layer: primitives, router, data, motionSolid Router, SolidStart (SSR), stores, large ecosystem
Maturityv0.1 prereleaseMature, production

Common ground

This is the closest reactivity match of any comparison here:

  • Signals with the same ergonomics. Read by calling (count()), fine-grained updates, derived values via memos/computed, side effects via effects.
  • No virtual DOM, no re-render. Both compile JSX to direct DOM operations and update only the exact bindings that changed.
  • Compile-time JSX. Neither ships a template runtime that re-evaluates a render function.

Naos's README is explicit that it wants "Solid-inspired ergonomics without depending on Solid runtime semantics." This page is the honest version of that: credit where the model comes from.

Where they diverge

Output boundary — the real difference

Solid's default target is an application: you call render() with your root component and a mount node, and Solid owns a subtree of the page. Custom elements are possible, but through the separate solid-element package, which wraps a Solid component as a Custom Element (with Shadow DOM) — an add-on, not the core model.

Naos inverts that. The Custom Element is the primary output: every compiled component is a registered element with Shadow DOM, slots, part styling, Declarative Shadow DOM prerender, and a form-associated path. There is no "app root" concept in the component model — the element itself is the unit of distribution.

So Solid is a reactive application library that can also emit custom elements, while Naos is a custom-element compiler that happens to share Solid's reactivity.

Runtime

Solid ships a small reactivity runtime with the app. Naos compiles more of that away at the element boundary and shares a small, tree-shakeable execution kernel for lifecycle and direct DOM mechanics (it is deliberately not a component runtime).

Implementation

Solid's JSX transform is Babel-based. Naos owns compiler semantics in Rust / OXC behind an N-API boundary.

Ecosystem shape

Solid has a mature ecosystem — Solid Router, SolidStart (SSR meta-framework), stores, and more. Naos ships its own optional layer (router, data, motion, primitives) but is early and narrower, and oriented around custom-element distribution rather than full application hosting.

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 onClick={() => count.set(count() + 1)}>
      Count: {count()}
    </button>
  )
}

Solid — a function component rendered into the page:

import { createSignal } from "solid-js"
import { render } from "solid-js/web"

function Counter() {
  const [count, setCount] = createSignal(0)
  return (
    <button onClick={() => setCount(count() + 1)}>
      Count: {count()}
    </button>
  )
}

render(() => <Counter />, document.getElementById("root")!)

The reactivity reads almost identically. The difference is the last line: Solid mounts into a root; a Naos Counter is registered as an element and used as a tag anywhere.

Which one fits

Reach for Solid when:

  • you are building a full application and want a mature reactive library with a real router and SSR meta-framework (SolidStart)
  • custom-element output is optional for you, not the primary artifact
  • you want the larger, more proven ecosystem today

Reach for Naos when:

  • the Custom Element is the deliverable — a design system or embeddable widget that any framework consumes as a tag
  • you want the same signal ergonomics but with Shadow DOM, slots, part, Declarative Shadow DOM, and form-associated elements built in
  • a Rust/OXC compiler core and a narrow, statically analyzable surface appeal to you
  • you are comfortable adopting a v0.1 prerelease

Honest caveats

  • Naos is a v0.1 prerelease; Solid is mature and production-proven.
  • The reactivity resemblance is real and acknowledged — Naos does not claim to have invented this model; it adapts it without depending on Solid's runtime.
  • solid-element is a capable path to custom elements; "Solid can't do custom elements" would be wrong. The difference is which model is the default.
  • Treat this as a July 2026 snapshot and re-check both projects' current docs.

Sources