Introduction

#What is BarefootJS?

BarefootJS is a compiler. It takes a JSX component and splits it into a marked template for your server and a client script for the browser.

"use client"
import { createSignal } from '@barefootjs/client'

export function Counter() {
  const [count, setCount] = createSignal(0)

  return (
    <button onClick={() => setCount(n => n + 1)}>
      Count: {count()}
    </button>
  )
}

The marked template renders the HTML with bf-* attributes that tell the client script where to attach:

export function Counter({ __instanceId, ... }) {
  const __scopeId = __instanceId || `Counter_${Math.random().toString(36).slice(2, 8)}`
  const count = () => 0

  return (
    <button bf-s={__scopeId} bf="s1">
      Count: {bfText("s0")}{count()}{bfTextEnd()}
    </button>
  )
}

The client script creates the signal, wires an effect to the s0 text slot, and binds the click handler to s1 — How It Works shows the generated code.

#Why BarefootJS

  • Backend freedom. The compiler emits native templates for Hono, Go, Perl, Ruby, Python, PHP, Rust and Java, so no Node.js runs at serving time. Adapters lists every backend.
  • MPA-style. Components are server-rendered by default; "use client" opts a component into shipping JavaScript. Your routing, data fetching and deployment stay as they are.
  • Fine-grained reactivity. Components run once. The compiler connects each signal to the DOM nodes that read it, and an update touches only those nodes — no virtual DOM, no re-render. See Reactivity.

Only the components you mark ship JavaScript:

// ProductPage.tsx — server component
import { AddToCart } from './AddToCart'    // "use client"
import { ReviewStars } from './ReviewStars' // "use client"

export function ProductPage({ product }) {
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <img src={product.image} />
      <ReviewStars rating={product.rating} />
      <AddToCart productId={product.id} />
    </div>
  )
}

h1, p and img produce zero JS. ReviewStars and AddToCart become interactive after hydration; the HTML is visible before that.

Continue with the Quick Start to scaffold an app, or How It Works for compilation and hydration in detail.