Quick Start

One command scaffolds a working JAF app and its dependencies.

Create a Project

pnpm create jaf my-app

Choose a Template

The scaffolder asks which template you want.

Pass --template to skip the question:

Template Best for
blank Starting from nothing, with the wiring already done.
basic The default. A home page, an about page, a layout and two sample components.
full Learning. Adds data fetching, persisted state, modals, toasts, a dynamic route and a theme toggle.
pnpm create jaf my-app --template full

See the CLI reference for every flag.

What You Get

my-app
skills/

Select a file to see what it is for

There is no route configuration (unless you prefer to use a config file).

pages/about.html is /about

pages/about/index.html is /about

pages/components/Button.html is <Button /> - anywhere in your app, without requiring an import statement.

Your Assistant Comes Configured

JAF is an LLM-optimized framework.

Every template ships JAF's skills library as llm/skills/, plus an AGENTS.md (and a CLAUDE.md pointing at it) that tells your coding assistant to read the relevant skill before writing any JAF code.

Your First Component

Create pages/components/Counter.html.

A component is one file: an optional script, a template, and optional scoped styles.

<script>
let count = 0
</script>

<button class="qs-counter" onclick="count++">
  Clicked <span class="qs-count">{count}</span> times
</button>
output

let makes a variable reactive. Everything that reads it will be updated when the value changes.

const stays static. That is the whole model.

Use it from any page - no import statement:

source
<!-- pages/index.html -->
<h1>Home</h1>
<Counter />

Project Scripts

Script What it does
dev Dev server with hot module replacement and an error overlay
build Production build into dist/ with per-route code splitting
preview Serve the production build locally
typecheck tsc --noEmit across the project

Adding JAF to an Existing Project

JAF is a set of Vite plugins, so it drops into an existing Vite app:

pnpm add jafjs
source
// vite.config.ts
import { defineConfig } from 'vite'
import {
  jafExpressionPlugin,
  jafPlugin,
  fileRouterPlugin,
  jafComponentsPlugin,
} from 'jafjs/vite'

export default defineConfig({
  plugins: [
    jafExpressionPlugin(),
    jafPlugin(),
    fileRouterPlugin(),
    jafComponentsPlugin(),
  ],
})

Then add src/entry-client.ts with a single line, and point your shell's module script at it:

source
import 'jafjs/entry-client'

Scaffolding a fresh project and copying your code across can be quicker than wiring this by hand.