Kita Html is a monorepo containing a super-fast JSX runtime that generates HTML strings. Unlike React, which builds a virtual DOM, this library directly produces HTML strings, making it ideal for server-side rendering, static site generation, and HTMX-style applications.
kitajs/html/
βββ packages/
β βββ html/ # Core JSX runtime (@kitajs/html)
β βββ ts-html-plugin/ # XSS detection TypeScript plugin (@kitajs/ts-html-plugin)
β βββ fastify-html-plugin/# Fastify integration (@kitajs/fastify-html-plugin)
β βββ docs/ # Documentation site (@kitajs/docs-html)
βββ benchmarks/ # Performance benchmarks
βββ examples/ # Usage examples
@kitajs/html (core)
β
βββ @kitajs/ts-html-plugin (peer dependency)
β
βββ @kitajs/fastify-html-plugin (peer dependency)
pnpm install # Install dependencies (pnpm required)
pnpm build # Build all packages
pnpm test # Run all tests
pnpm format # Format code
pnpm bench # Run benchmarksSee CONTRIBUTING.md for full development workflow, per-package commands, and pull request guidelines.
// Input (JSX)
<div class="hello">{name}</div>;
// TypeScript transforms to
jsx('div', { class: 'hello', children: name });
// Output (string)
('<div class="hello">Arthur</div>');- No Virtual DOM: Direct string concatenation for maximum performance
- Type as String:
JSX.Element = string | Promise<string> - Async Propagation: Promise children make parent promises
- XSS by Default: Children are NOT escaped unless
safeattribute is used - Compile-Time Safety: TypeScript plugin catches XSS at development time
User Code (TSX)
β
βΌ
TypeScript Compiler
β (jsx: "react-jsx", jsxImportSource: "@kitajs/html")
βΌ
jsx-runtime.ts (jsx/jsxs functions)
β
βΌ
index.ts (createElement, attributesToString, contentsToString)
β
βΌ
HTML String (or Promise<string> for async)
User writes JSX
β
βΌ
ts-html-plugin (LSP) ββββββΊ Warnings/Errors in Editor
β
βΌ
xss-scan (CLI) βββββββββββββΊ CI/CD Pipeline Check
β
βΌ
Runtime (safe attribute) βββΊ Escapes at render time
The core JSX runtime. Key files:
src/index.ts: Escaping, attribute handling, element creationsrc/jsx-runtime.ts: Modern JSX transform (jsx,jsxs,Fragment)src/suspense.ts: Streaming HTML with async componentssrc/error-boundary.ts: Error handling for async trees
TypeScript plugin for XSS detection. Key files:
src/index.ts: Language Service Plugin entrysrc/cli.ts:xss-scanCLI toolsrc/util.ts: Core detection algorithmssrc/errors.ts: Error codes (TS88601-TS88604)
See: packages/ts-html-plugin/CLAUDE.md
Fastify integration. Key file:
src/index.ts: Plugin registration,reply.html(), Suspense streaming
See:
packages/fastify-html-plugin/CLAUDE.md
Documentation site at https://html.kitajs.org. Uses Rspress, follows Information Mapping methodology.
| Tool | Purpose |
|---|---|
| pnpm | Package manager (required) |
| TypeScript 5.9+ | Language |
| tsgo | TypeScript compiler (native preview) |
| Vitest | Test runner |
| c8/v8 | Code coverage |
| Prettier | Code formatting |
| Husky | Git hooks |
| Changesets | Version management |
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@kitajs/html",
"plugins": [{ "name": "@kitajs/ts-html-plugin" }],
"strict": true,
"module": "CommonJS",
"target": "ESNext"
}
}{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}The codebase uses several optimization patterns:
-
Check Before Convert: Regex test before expensive operations
if (!CAMEL_REGEX.test(camel)) return camel;
-
Loop vs Regex: Character loops faster than regex for replacements
for (; end < length; end++) { switch (value[end]) { ... } }
-
Escape Once: Escape entire result string, not individual pieces
-
Void Element Ordering: Most common tags first in checks
-
Bun Detection: Use native
Bun.escapeHTMLwhen available
- Compile-Time:
@kitajs/ts-html-plugincatches unsafe usage - CI/CD:
xss-scanCLI fails builds on XSS issues - Runtime:
safeattribute escapes content
- Numbers, booleans, bigints
- String literals
JSX.Element(already rendered)Html.Childrentype- Variables prefixed with
safe Html.escapeHtml()calls
string(dynamic)anytype- Objects with
toString() - Variables prefixed with
unsafe
Any change to the runtime, types, API surface, configuration, or behavior of any package
must include a corresponding update to the documentation at packages/docs/. If a code
change would make any existing documentation page inaccurate, update that page in the same
commit. Use the docs-writer agent at .claude/agents/docs-writer/ for documentation
work. Run pnpm -F @kitajs/docs-html build to verify the docs site compiles after any
documentation change.
import type { PropsWithChildren } from '@kitajs/html';
function Card({ title, children }: PropsWithChildren<{ title: string }>) {
return (
<div class="card">
<h2 safe>{title}</h2>
{children}
</div>
);
}async function UserProfile({ id }: { id: string }) {
const user = await db.getUser(id);
return <div safe>{user.name}</div>;
}function Page({ rid }: { rid: number }) {
return (
<Suspense rid={rid} fallback={<Loading />} catch={(e) => <Error error={e} />}>
<AsyncContent />
</Suspense>
);
}
// With Fastify
app.get('/', (req, reply) => reply.html(<Page rid={req.id} />));<div class={['base', isActive && 'active', size]} />- Children NOT escaped by default - Always use
safefor user input JSX.Elementisstring | Promise<string>- Handle both cases- Suspense needs
rid- Use request ID for concurrent safety - Components receive
safeas a prop - They must forward it to inner native elements - pnpm required - npm/yarn will fail on install