#What is BarefootJS?
BarefootJS is a compiler that transforms JSX components into server-rendered templates and minimal client-side JavaScript.
Write familiar JSX with fine-grained reactivity — the compiler splits it into a marked template for your backend and a tiny hydration 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>
)
}This single file compiles into two outputs:
Marked template — Renders static HTML with hydration markers:
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>
)
}Marked template — Go html/template with hydration markers:
{{define "Counter"}}
<button bf-s="{{bfScopeAttr .}}" bf="s1">
Count: {{bfTextStart "s0"}}{{.Count}}{{bfTextEnd}}
</button>
{{end}}Client script — Wires up only the interactive parts:
import { $, createEffect, createSignal, escapeText, escapeTextOrNode, hydrate, lazySlots } from '@barefootjs/client/runtime'
export function initCounter(__scope, _p = {}) {
if (!__scope) return
const [count, setCount] = createSignal(0)
const [_s1] = $(__scope, 's1') // find element with bf="s1"
// Claim the content slot between <!--bf:s0--> and <!--/--> on first
// write; later writes reuse the claimed reference (no re-scanning)
const __bfw_s0 = lazySlots(__scope, [{ id: 's0', kind: 'markup', path: [] }])
createEffect(() => {
const __val = count()
__bfw_s0('s0', escapeTextOrNode(__val))
})
if (_s1) _s1.addEventListener('click', () => { setCount(n => n + 1) })
}
hydrate('Counter', {
init: initCounter,
template: (_p) => `<button bf="s1"> Count: <!--bf:s0-->${escapeText((0))}<!--/--></button>`
})