` elements. Pick this when you want to wire up your own styling. Pass `--css none` to select it non-interactively.
## 2. Install and run
```bash
cd my-app
npm install
npm run dev
```
`npm run dev` runs three processes in parallel:
- `bf build --watch` — the BarefootJS compiler. Watches `components/` and emits marked templates plus client JS to `public/components/`.
- `unocss --watch` — scans your JSX for utility classes and writes `public/uno.css`.
- `wrangler dev --live-reload` — Cloudflare's local Workers runtime. Serves the app and reloads the browser on rebuilds.
Open the URL Wrangler prints. You should see a counter card with **+1**, **-1**, and **Reset** buttons.
## 3. Look at what was generated
```
my-app/
├── server.tsx # Hono routes — entry point
├── renderer.tsx # HTML shell (, , BfScripts)
├── components/
│ └── Counter.tsx # The starter component
├── components/ui/
│ └── button/ # Pulled from the BarefootJS UI registry
├── public/ # Static assets served by Workers
│ ├── tokens.css # CSS design tokens
│ ├── styles.css # Counter + page styles
│ └── components/ # Generated client JS (bf build writes here)
├── barefoot.config.ts # Compiler + paths config
├── wrangler.jsonc # Cloudflare Workers config
└── uno.config.ts # UnoCSS scan patterns
```
Open `components/Counter.tsx`:
```tsx
'use client'
import { createSignal, createMemo } from '@barefootjs/client'
import { Button } from '@/components/ui/button'
interface CounterProps {
initial?: number
}
export function Counter(props: CounterProps) {
const [count, setCount] = createSignal(props.initial ?? 0)
const doubled = createMemo(() => count() * 2)
return (
count: {count()}
doubled: {doubled()}
setCount(n => n + 1)}>+1
setCount(n => n - 1)} variant="secondary">-1
setCount(0)} variant="ghost">Reset
)
}
```
See [Client Directive](./rendering/client-directive.md), [`createSignal`](./reactivity/create-signal.md), and [`createMemo`](./reactivity/create-memo.md) for what each piece does. Props are read via `props.initial`, not destructured — destructuring captures the value once and breaks reactivity, so the compiler emits warning [`BF043`](./advanced/error-codes.md) when it sees that form on a `"use client"` component. [Props Reactivity](./reactivity/props-reactivity.md) covers the full rule.
The Counter is mounted in `server.tsx`:
```tsx
import { Hono } from 'hono'
import { renderer } from './renderer'
import { Counter } from '@/components/Counter'
const app = new Hono()
app.use('*', renderer)
app.get('/', (c) =>
c.render(
,
{ title: 'BarefootJS app' },
),
)
export default app
```
Same `Counter` import, two outputs: server renders HTML, client hydrates the buttons.
## 4. Make a change
With `npm run dev` still running, pass an initial value from the server. In `server.tsx`:
```tsx
app.get('/', (c) =>
c.render(
,
{ title: 'BarefootJS app' },
),
)
```
Save. The browser reloads and the counter starts at **5**. The server rendered `5` into the HTML, and hydration picked it up on the client — the same JSX, evaluated in both places.
Now add a new button to `Counter.tsx`:
```tsx
setCount(n => n * 2)} variant="ghost">×2
```
Save and watch the browser update. No virtual DOM, no diff — the compiler generated an effect that updates only the `` text node when `count` changes.
## 5. Deploy (optional)
When you're ready to ship:
```bash
npm run deploy
```
This runs `bf build`, generates the final `uno.css`, and calls `wrangler deploy`. The first deploy will prompt you to log into Cloudflare. After that, your app is live on `*.workers.dev`.
## Next steps
- **[Agent Skill](./core-concepts/ai-native.md#agent-skill)** — Install the BarefootJS skill for Claude Code or Codex and let the agent build components, write IR tests, and debug signals for you.
- **[Core Concepts](./core-concepts.md)** — the four design principles behind BarefootJS: backend freedom, MPA-style rendering, fine-grained reactivity, and AI-native workflows.
- **[`createSignal`](./reactivity/create-signal.md)** and **[`createMemo`](./reactivity/create-memo.md)** — the reactivity primitives you just used.
- **[Client Directive](./rendering/client-directive.md)** — exactly what `"use client"` does and when to reach for it.
- **[Hono Adapter](./adapters/hono-adapter.md)** — adapter-specific configuration and output details.
- Pick a different backend by passing `--adapter` to the scaffolder. Supported values today: `hono` (default — Cloudflare Workers), `hono-node`, `echo` (Go / Echo), `gin` (Go / Gin), `chi` (Go / Chi), `nethttp` (Go / net/http stdlib), `mojo` (Mojolicious / Perl), `csr` (no backend — pure client render). For example:
```bash
npm create barefootjs@latest -- --adapter hono-node
```
See [Adapter Architecture](./adapters/adapter-architecture.md) for the architectural overview, and the per-adapter pages under [`docs/core/adapters/`](./adapters/) for output details. The four Go scaffolds (`echo`, `gin`, `chi`, `nethttp`) all build on the `@barefootjs/go-template` adapter, which generates Go `html/template` files; see [Go Template Adapter](./adapters/go-template-adapter.md) for its programmatic API.