Skip to content
K

Getting Started

Install Naos packages and compile TSX Web Components.

Naos v0.1 is a prerelease compiler toolchain for building native Custom Elements from a React-like TSX subset. You write typed component functions; the browser receives platform code.

Read the docs in this order when you are new to the project:

  1. Getting Started for install, TypeScript, Vite, and the first component.
  2. Authoring Surface for props, state, events, control flow, and composition.
  3. Styling And DSD for CSS, theming, prerendering, and hydration behavior.
  4. Packages and API Reference for package boundaries and callable APIs.
  5. Demos for the browser proof and local verification commands.

Install

pnpm add @naos-ui/core @naos-ui/runtime
pnpm add -D @naos-ui/compiler @naos-ui/vite @naos-ui/cli

@naos-ui/compiler installs one optional native package for the current platform. There is no npm source-build fallback in v0.1.

Configure TypeScript

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@naos-ui/core",
    "types": ["vite/client"]
  }
}

Configure Vite

import { defineConfig } from "vite"
import { naos } from "@naos-ui/vite"

export default defineConfig({
  plugins: [naos()],
})

Vite owns modules, chunks, assets, cache invalidation, and CSS imports. Naos only transforms accepted .wc.tsx component modules.

Author A Component

import { computed, event, state, type ComponentOptions } from "@naos-ui/core"
import css from "./counter.wc.css?inline"

export const options = {
  styles: [css],
} satisfies ComponentOptions

export function Counter({ label = "Count" } = {}) {
  const count = state(0)
  const text = computed(() => `${label}: ${count()}`)
  const change = event<number>("change")

  return (
    <button
      part="button"
      data-count={count()}
      onClick={() => {
        count.update((value) => value + 1)
        change.emit(count())
      }}
    >
      {text()}
    </button>
  )
}

The compiler infers the native Custom Element tag from the file and export. Host pages consume the result with regular DOM APIs.

CLI

naos compile src/counter.wc.tsx -o dist/counter.js
naos prerender src/counter.wc.tsx --props '{"label":"Static"}'
naos info

Use the CLI for smoke tests, standalone transforms, and static HTML output. Application builds should use the Vite plugin.

Static HTML And DSD

Declarative Shadow DOM is the default HTML output inside the prerender path:

naos prerender src/counter.wc.tsx --props '{"label":"Static"}' -o dist/counter.html

In Vite builds, prerender metadata is on by default so a static site or demo build can discover compiled Naos components:

naos({
  prerender: {
    manifestFile: "naos-manifest.json",
  },
})

The snippet above only customizes the manifest path. naos() already uses naos-manifest.json. Use prerender: false only when a build should not emit static HTML metadata.

There is no component-level DSD switch. If you prerender an Naos component, Naos emits <template shadowrootmode="open"> host HTML and the client module hydrates it on upgrade.

Native Install Checks

If the compiler cannot load its native binding, run:

naos info

The output shows the detected platform and native package. Published installs should load the matching @naos-ui/compiler-* package. Repository development uses a local binding built with:

pnpm -w build:native

What Naos Is Not

Naos is not a React compatibility layer, a virtual DOM renderer, a bundler, or a framework adapter. Vite owns modules, chunks, assets, and CSS loading. Naos only compiles accepted .wc.tsx modules into native Custom Elements.