Prerequisites
- A Hono project. Run
bun create hono@latestto scaffold one. - Tailwind v4. Imported via
@import "tailwindcss"in your stylesheet. - TypeScript. The CLI wires up
@/path aliases andjsxImportSourcefor you.
Install
Run the CLI
Run this in the root of your Hono project.
npx @kiwa-ui/cli initWhat init does
Creates project structure, writes templates, and installs base dependencies.
| Target | Purpose |
|---|---|
components/uicomponents/blockslibstyles | Directories created. |
lib/utils.ts | The cn() helper. |
styles/globals.css | Full token contract. See Theming. |
kiwa-ui.json | CLI config file. |
tsconfig.json | Adds @/components and @/lib/utils path aliases. |
clsxtailwind-mergelucide | Installed as npm dependencies. |
Add a component
Pick something to start with. Button is a common first pick.
npx @kiwa-ui/cli add buttonImport globals.css and use the component
import { Hono } from 'hono'
import { Button } from './components/ui/button'
import './styles/globals.css'
const app = new Hono()
app.get('/', (c) =>
c.html(
<html>
<body>
<Button variant='default'>Click me</Button>
</body>
</html>
)
)
export default appInstall peer dependencies
These are the only runtime deps Kiwa UI expects.
pnpm add clsx tailwind-merge lucideCreate lib/utils.ts
The cn() helper merges Tailwind classes with clsx + tailwind-merge.
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}Create styles/globals.css
Tailwind v4 is CSS-first. All config lives here.
@import "tailwindcss";
@custom-variant dark (&:is(.dark *));
@theme inline {
/* tokens go here, see the Theming page */
}Configure tsconfig path aliases
So you can import from @/components and @/lib/utils.
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}Copy a component from the registry
Grab the source file from registry/ui/ on GitHub and drop it into components/ui/.
Component source lives at github.com/kiwa-ui/kiwa-ui/tree/main/registry/ui. Copy the file, check its registryDependencies in registry/ui/index.ts, and copy those too.
The kiwa-ui.json config
kiwa-ui.json lives in your project root. The CLI reads it before every add to know where to write files and which components you already have.
{
"$schema": "https://registry.kiwaui.com/schema.json",
"tsconfig": "tsconfig.json",
"tailwind": {
"config": "tailwind.config.js",
"css": "styles/globals.css"
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
},
"components": []
}| Field | Description |
|---|---|
tailwind.css | Path to the CSS entry point; the CLI won't rewrite it, but it verifies the file exists. |
aliases | Path aliases used when generating import statements in copied components. |
components | Tracks what you've installed so npx @kiwa-ui/cli diff can detect drift against the registry. |
CLI commands
| Command | Description |
|---|---|
npx @kiwa-ui/cli init | Scaffold the project. Pass --force to overwrite an existing config. |
npx @kiwa-ui/cli add <names…> | Install one or more components or blocks. Registry dependencies are resolved recursively. |
npx @kiwa-ui/cli diff | Check installed components against the registry. Pass --apply to pull updates. |
Licenses (pro blocks)
Pro blocks are gated behind a license token. Set KIWA_UI_TOKEN in your environment and the CLI will send it as a Bearer header.
# .env.local (never commit this)
KIWA_UI_TOKEN=your_license_key_here