Introduction
Estimated reading time: 4 minutesKita Html is a JSX runtime where every element evaluates to a string. Where React's
<div /> produces a virtual DOM node that must be reconciled and serialized, Kita Html's
<div /> returns '<div></div>' directly. The JSX you write compiles to function calls
that concatenate strings.
This makes Kita Html faster than virtual DOM-based renderers whenever the output is an HTML string: server-side rendering, static site generation, email templates, HTMX applications, or any HTTP handler that sends HTML over the wire.
Performance through simplicity
On each render, a virtual DOM renderer constructs an object tree, diffs it against the
previous tree, and serializes the result to a string. Kita Html does none of this. The
TypeScript compiler rewrites JSX expressions into jsx() and jsxs() function calls at
build time. At runtime, those functions concatenate attribute strings and child strings
into a single result. The output is the final HTML with no post-processing.
In the RealWorldPage benchmark, Kita Html renders about 2-3x
faster than React, Preact, and HonoJsx. The only dependency is csstype, which provides
types for the style attribute.
Read more about compilation and rendering
XSS protection
Because JSX.Element is a plain string (or a promise of one), the runtime cannot
distinguish between HTML produced by a component and raw user input injected as a child.
Children are not escaped by default. This is a deliberate trade-off for performance and
composability. The safe attribute and the kita-html check CLI close that gap.
The safe attribute escapes children at render time. Adding it to any native element
causes the runtime to pass all children through HTML entity escaping before concatenation.
kita-html check uses the TypeScript 7.1 type checker to analyze
every JSX expression and flags any child whose type could carry unescaped HTML. It runs in
CI/CD pipelines, failing the build on any finding, and can feed editor problem panels.
Values that bypass the type system, such as as 'safe' casts or safe-prefixed names,
are not checked.
Read more about the XSS protection system
Async components and Suspense
Kita Html supports async components natively. Any function component that returns a
Promise<string> is valid JSX. When an async child appears anywhere in the tree, the
entire parent chain becomes a Promise<string> through automatic propagation.
For streaming scenarios, the Suspense component renders a fallback immediately and replaces it with the resolved content as each async subtree completes. This uses HTTP chunked transfer encoding to stream updates to the client without waiting for the entire page to resolve. A small inline script handles the client-side DOM replacement.
Each Suspense boundary operates independently, so fast components appear instantly while
slow ones show their fallback. The rid parameter ties each Suspense instance to a
specific request for safe concurrent rendering.
Read more about Suspense streaming
Packages
The main packages are:
@kitajs/htmlis the core runtime that renders JSX to strings and provides Suspense streaming.@kitajs/html-cliprovideskita-html check, the XSS scanner for TypeScript 7.1 and later.@kitajs/ts-html-pluginis the deprecated editor plugin andxss-scanCLI for TypeScript 6.
Official framework integrations are available for Fastify and Express, and Elysia provides its own. The core runtime works with any framework that accepts strings.
Read more about the packages and integrations
Built something interesting with Kita Html? Show us where you're using it.