---
title: Quick Start
description: Scaffold a BarefootJS app in under five minutes — Counter component, dev server, deploy.
---

# Quick Start

Scaffold a BarefootJS app, run it locally, and tour the generated project. About five minutes.

## Prerequisites

- **Node.js 22+** (or Bun, or Deno 2+).
- The default scaffold targets [Cloudflare Workers](https://developers.cloudflare.com/workers/) via `wrangler dev` — runs locally, no account needed.

## 1. Scaffold the project

<PackageManagerTabs command="barefootjs@latest" mode="create" />

Press Enter at the prompts to accept the defaults (Hono on Cloudflare Workers, UnoCSS).

The CSS prompt has two options:

- **UnoCSS** (default) — wires up UnoCSS and pulls a starter `<Button>` from the BarefootJS UI registry. The rest of this guide follows this path.
- **None (bring your own CSS)** — no UnoCSS, no UI components, no stylesheets. You get just the JSX→template+signals compiler output and a dependency-free starter `Counter` built from native `<button>` 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 (<head>, <body>, 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 (
    <div className="counter">
      <p className="counter-value">count: {count()}</p>
      <p className="counter-doubled">doubled: {doubled()}</p>
      <div className="counter-buttons">
        <Button onClick={() => setCount(n => n + 1)}>+1</Button>
        <Button onClick={() => setCount(n => n - 1)} variant="secondary">-1</Button>
        <Button onClick={() => setCount(0)} variant="ghost">Reset</Button>
      </div>
    </div>
  )
}
```

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(
    <main>
      <Counter />
    </main>,
    { 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(
    <main>
      <Counter initial={5} />
    </main>,
    { 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
<Button onClick={() => setCount(n => n * 2)} variant="ghost">×2</Button>
```

Save and watch the browser update. No virtual DOM, no diff — the compiler generated an effect that updates only the `<p>` 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.
