# Getting Started

> Install koze, koze/vite, and boot a first app on Cloudflare Workers

Package: Koze
Canonical: https://kuratchi.dev/docs/koze/getting-started
Markdown: https://kuratchi.dev/docs/koze/getting-started.md

## Install

Koze is **Vite-first**. Every new project runs through `vite dev` / `vite build` with the Koze plugin.

### Scaffold with `koze`

```bash
npx koze create my-app
cd my-app
bun install
bun run dev
```

The scaffolder drops a working Vite project with routes, assets, and a `wrangler.jsonc` pointed at `src/worker.ts`.

### Or install into an existing project

```bash
npm install @kuratchi/koze
npm install -D vite wrangler @cloudflare/workers-types
```

Optional packages (install only what you need):

| Package | When |
| --- | --- |
| `kunii` | D1 / Durable Object SQLite schema + query builder |
| `kyzen` | Credentials, sessions, OAuth, RBAC, Turnstile |
| `kuzan` | Ready-made HTML component library |
| `tailwindcss` `@tailwindcss/vite` | Tailwind CSS (plain Vite plugin) |
| `lightningcss` | CSS transformer (configure via `vite.config.ts`) |

## Minimal project shape

```text
my-app/
├─ package.json
├─ vite.config.ts
├─ wrangler.jsonc
├─ tsconfig.json
└─ src/
   ├─ worker.ts                    export { default } from 'koze:worker'
   ├─ middleware.ts                defineMiddleware({ ... })
   ├─ app.koze                 document shell
   ├─ app.css                      global stylesheet (optional)
   ├─ assets/                      static files served verbatim at /
   ├─ server/                      auto-discovered DOs / workflows / queues / pipelines / containers
   └─ routes/
      ├─ layout.koze           shared fragment
      └─ index.koze            /
```

There is no project-level config file. Build-time options (security headers, directory overrides) are passed to the `koze()` Vite plugin. Request-time concerns (auth, ORM auto-migration, custom steps) live in `src/middleware.ts`.

For a full reference of every special file, see [Project structure](/docs/koze/project-structure).

## `vite.config.ts`

The Koze plugin owns routing, virtual modules, and Wrangler sync. Nothing else to configure for the common case.

```ts
import { defineConfig } from 'vite';
import { koze } from '@kuratchi/koze/vite';

export default defineConfig({
  plugins: [koze()],
});
```

## `wrangler.jsonc`

```jsonc
{
  "name": "my-app",
  "main": "src/worker.ts",
  "compatibility_date": "2026-01-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": { "directory": "src/assets" }
}
```

The Koze plugin auto-maintains `durable_objects`, `containers`, `queues.consumers`, `pipelines`, and `migrations[]` entries based on what it discovers in `src/server/`. Do not hand-edit those fields.

## `package.json` scripts

```json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "deploy": "vite build && wrangler deploy"
  }
}
```

## `src/worker.ts`

```ts
export { default } from 'koze:worker';
```

That's the whole file. The virtual module synthesizes `fetch` + `queue` handlers, Durable Object exports, and any discovered convention classes.

## `src/app.koze` — document shell

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>My App</title>
</head>
<body>
  <slot></slot>
</body>
</html>
```

Optional — the framework provides a minimal default shell when absent. Don't add a `<link>` for your global CSS; Koze injects it (see next section).

## `src/routes/layout.koze` — shared fragment

Wraps every page. Not a document — no `<!DOCTYPE>`, no `<html>`.

```html
<script>
  import { url } from 'koze:request';
  const current = url.pathname;
</script>

<header>
  <a href="/" class={current === '/' ? 'active' : ''}>Home</a>
  <a href="/about" class={current === '/about' ? 'active' : ''}>About</a>
</header>

<main>
  <slot></slot>
</main>
```

## `src/routes/index.koze` — first page

```html
<script>
  const items = ['Alpha', 'Bravo', 'Charlie'];
</script>

<h1>Hello Koze</h1>

if (items.length > 0) {
  <ul>
    for (const item of items) {
      <li>{item}</li>
    }
  </ul>
} else {
  <p>No items yet.</p>
}
```

The page is server-rendered. The top `<script>` runs during SSR; `$server/*` imports become RPC stubs when the same code runs in the browser.

## First stylesheet — `src/app.css`

Drop a file at `src/app.css`. Koze registers it as a Vite client entry, runs every CSS plugin on it (Tailwind, PostCSS, CSS Modules, Lightning CSS), and auto-injects `<link rel="stylesheet">` into your app shell before `</head>`. You don't write the `<link>` tag.

```css
/* src/app.css */
body {
  margin: 0;
  font-family: system-ui, sans-serif;
}
```

That's the full setup. Add Tailwind by installing `@tailwindcss/vite`, dropping it into `vite.config.ts`, and `@import "tailwindcss"` from `src/app.css`. See [Styling](/docs/koze/styling) for Tailwind, CSS frameworks, and static asset conventions.

## First browser-side JavaScript

Koze routes have one script block. Declare a handler in the top
`<script>` and bind it with `onclick={fn(args)}`:

```html
<script>
  import { deleteItem } from '$server/items';

  async function confirmDelete(id) {
    if (!confirm('Delete?')) return;
    await deleteItem(id);
    location.reload();
  }
</script>

<ul>
  for (const item of items) {
    <li>
      {item.title}
      <button onclick={confirmDelete(item.id)} type="button">Delete</button>
    </li>
  }
</ul>
```

The same script runs on the server (resolving the `await`) and in the
browser (wiring up `confirmDelete`). No `addEventListener`, no
`document.querySelector`, no `typeof document` guards.

See [Client interactivity](/docs/koze/client-interactivity) for the
event-handler reference, SSR data hydration, and browser-only DOM
patterns inside the single route script.

## Run locally

```bash
bun install
bun run dev
```

`vite dev` serves the app on `http://localhost:5173` with the Cloudflare Vite plugin providing a Workers-accurate runtime.

## What to read next

- [Project structure](/docs/koze/project-structure) — every special file reference
- [Configuration](/docs/koze/configuration) — where each kind of config lives
- [Routing](/docs/koze/routing) — dynamic segments, template syntax, components
- [Actions](/docs/koze/actions) — native form POSTs with server functions
- [Middleware](/docs/koze/middleware) — request lifecycle, hooks, composition
- [Request APIs](/docs/koze/request-apis) — `koze:request`, redirects, env helpers
- [ORM Getting Started](/docs/kunii/getting-started) — schemas, migrations, queries
- [Auth Getting Started](/docs/kyzen/getting-started) — credentials, sessions, OAuth, RBAC
